5.15.167-rc1 review
Greg Kroah-Hartman
maintainerPATCH 150/214 wifi: mwifiex: Do not return unused priv in mwifiex_get_priv_by_id()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sascha Hauer <[email protected]>
[ Upstream commit c145eea2f75ff7949392aebecf7ef0a81c1f6c14 ]
mwifiex_get_priv_by_id() returns the priv pointer corresponding to the bss_num and bss_type, but without checking if the priv is actually currently in use.
Unused priv pointers do not have a wiphy attached to them which can lead to NULL pointer dereferences further down the callstack. Fix this by returning only used priv pointers which have priv->bss_mode set to something else than NL80211_IFTYPE_UNSPECIFIED.
Said NULL pointer dereference happened when an Accesspoint was started with wpa_supplicant -i mlan0 with this config:
network={
ssid="somessid"
mode=2
frequency=2412
key_mgmt=WPA-PSK WPA-PSK-SHA256
proto=RSN
group=CCMP
pairwise=CCMP
psk="12345678"
}When waiting for the AP to be established, interrupting wpa_supplicant with <ctrl-c> and starting it again this happens:
| Unable to handle kernel NULL pointer dereference at virtual address 0000000000000140 | Mem abort info: | ESR = 0x0000000096000004 | EC = 0x25: DABT (current EL), IL = 32 bits | SET = 0, FnV = 0 | EA = 0, S1PTW = 0 | FSC = 0x04: level 0 translation fault | Data abort info: | ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000 | CM = 0, WnR = 0, TnD = 0, TagAccess = 0 | GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0 | user pgtable: 4k pages, 48-bit VAs, pgdp=0000000046d96000 | [0000000000000140] pgd=0000000000000000, p4d=0000000000000000 | Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP | Modules linked in: caam_jr caamhash_desc spidev caamalg_desc crypto_engine authenc libdes mwifiex_sdio +mwifiex crct10dif_ce cdc_acm onboard_usb_hub fsl_imx8_ddr_perf imx8m_ddrc rtc_ds1307 lm75 rtc_snvs +imx_sdma caam imx8mm_thermal spi_imx error imx_cpufreq_dt fuse ip_tables x_tables ipv6 | CPU: 0 PID: 8 Comm: kworker/0:1 Not tainted 6.9.0-00007-g937242013fce-dirty #18 | Hardware name: somemachine (DT) | Workqueue: events sdio_irq_work | pstate: 00000005 (nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) | pc : mwifiex_get_cfp+0xd8/0x15c [mwifiex] | lr : mwifiex_get_cfp+0x34/0x15c [mwifiex] | sp : ffff8000818b3a70 | x29: ffff8000818b3a70 x28: ffff000006bfd8a5 x27: 0000000000000004 | x26: 000000000000002c x25: 0000000000001511 x24: 0000000002e86bc9 | x23: ffff000006bfd996 x22: 0000000000000004 x21: ffff000007bec000 | x20: 000000000000002c x19: 0000000000000000 x18: 0000000000000000 | x17: 000000040044ffff x16: 00500072b5503510 x15: ccc283740681e517 | x14: 0201000101006d15 x13: 0000000002e8ff43 x12: 002c01000000ffb1 | x11: 0100000000000000 x10: 02e8ff43002c0100 x9 : 0000ffb100100157 | x8 : ffff000003d20000 x7 : 00000000000002f1 x6 : 00000000ffffe124 | x5 : 0000000000000001 x4 : 0000000000000003 x3 : 0000000000000000 | x2 : 0000000000000000 x1 : 0001000000011001 x0 : 0000000000000000 | Call trace: | mwifiex_get_cfp+0xd8/0x15c [mwifiex] | mwifiex_parse_single_response_buf+0x1d0/0x504 [mwifiex] | mwifiex_handle_event_ext_scan_report+0x19c/0x2f8 [mwifiex] | mwifiex_process_sta_event+0x298/0xf0c [mwifiex] | mwifiex_process_event+0x110/0x238 [mwifiex] | mwifiex_main_process+0x428/0xa44 [mwifiex] | mwifiex_sdio_interrupt+0x64/0x12c [mwifiex_sdio] | process_sdio_pending_irqs+0x64/0x1b8 | sdio_irq_work+0x4c/0x7c | process_one_work+0x148/0x2a0 | worker_thread+0x2fc/0x40c | kthread+0x110/0x114 | ret_from_fork+0x10/0x20 | Code: a94153f3 a8c37bfd d50323bf d65f03c0 (f940a000) | ---[ end trace 0000000000000000 ]---
--- drivers/net/wireless/marvell/mwifiex/main.h | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/wireless/marvell/mwifiex/main.h +3 -0
@@ -1310,6 +1310,9 @@ mwifiex_get_priv_by_id(struct mwifiex_adapter *adapter,for (i =0 ; i < adapter->priv_num; i++) {if (adapter->priv[i]) { +if (adapter->priv[i]->bss_mode ==NL80211_IFTYPE_UNSPECIFIED ) +continue ; +if ((adapter->priv[i]->bss_num == bss_num) && (adapter->priv[i]->bss_type == bss_type))break ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 151/214 smp: Add missing destroy_work_on_stack() call in smp_call_on_cpu()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zqiang <[email protected]>
[ Upstream commit 77aeb1b685f9db73d276bad4bb30d48505a6fd23 ]
For CONFIG_DEBUG_OBJECTS_WORK=y kernels sscs.work defined by INIT_WORK_ONSTACK() is initialized by debug_object_init_on_stack() for the debug check in __init_work() to work correctly.
But this lacks the counterpart to remove the tracked object from debug objects again, which will cause a debug object warning once the stack is freed.
Add the missing destroy_work_on_stack() invocation to cure that.
[ tglx: Massaged changelog ]
--- kernel/smp.c | 1 + 1 file changed, 1 insertion(+)
kernel/smp.c +1 -0
@@ -1233,6 +1233,7 @@ int smp_call_on_cpu(unsigned int cpu, int (*func)(void *), void *par, bool phys)queue_work_on (cpu, system_wq, &sscs.work);wait_for_completion (&sscs.done); +destroy_work_on_stack (&sscs.work);return sscs.ret; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 152/214 fs/ntfs3: Check more cases when directory is corrupted
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Konstantin Komarov <[email protected]>
[ Upstream commit 744375343662058cbfda96d871786e5a5cbe1947 ]
Mark ntfs dirty in this case.
Rename ntfs_filldir to ntfs_dir_emit.
--- fs/ntfs3/dir.c | 52 +++++++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 20 deletions(-)
fs/ntfs3/dir.c +32 -20
@@ -272,9 +272,12 @@ struct inode *dir_search_u(struct inode *dir, const struct cpu_str *uni,return err == -ENOENT ?NULL : err ?ERR_PTR (err) : inode; } -static inline int ntfs_filldir (struct ntfs_sb_info *sbi,struct ntfs_inode *ni, -const struct NTFS_DE *e,u8 *name, -struct dir_context *ctx) +/* +* returns false if 'ctx' if full +*/ +static inline bool ntfs_dir_emit (struct ntfs_sb_info *sbi, +struct ntfs_inode *ni,const struct NTFS_DE *e, +u8 *name,struct dir_context *ctx) {const struct ATTR_FILE_NAME *fname;unsigned long ino;
@@ -284,29 +287,29 @@ static inline int ntfs_filldir(struct ntfs_sb_info *sbi, struct ntfs_inode *ni, fname =Add2Ptr (e,sizeof (struct NTFS_DE ));if (fname->type ==FILE_NAME_DOS ) -return 0 ; +return true;if (!mi_is_ref (&ni->mi, &fname->home)) -return 0 ; +return true; ino =ino_get (&e->ref);if (ino ==MFT_REC_ROOT ) -return 0 ; +return true;/* Skip meta files. Unless option to show metafiles is set. */ if (!sbi->options->showmeta &&ntfs_is_meta_file (sbi, ino)) -return 0 ; +return true;if (sbi->options->nohidden && (fname->dup.fa &FILE_ATTRIBUTE_HIDDEN )) -return 0 ; +return true; name_len =ntfs_utf16_to_nls (sbi, fname->name, fname->name_len, name,PATH_MAX );if (name_len <=0 ) {ntfs_warn (sbi->sb,"failed to convert name for inode %lx." , ino); -return 0 ; +return true; }/*
@@ -336,17 +339,20 @@ static inline int ntfs_filldir(struct ntfs_sb_info *sbi, struct ntfs_inode *ni, } } -return !dir_emit (ctx, (s8 *)name, name_len, ino, dt_type); +return dir_emit (ctx, (s8 *)name, name_len, ino, dt_type); }/* * ntfs_read_hdr - Helper function for ntfs_readdir(). +* +* returns 0 if ok. +* returns -EINVAL if directory is corrupted. +* returns +1 if 'ctx' is full. */ static int ntfs_read_hdr (struct ntfs_sb_info *sbi,struct ntfs_inode *ni,const struct INDEX_HDR *hdr,u64 vbo,u64 pos,u8 *name,struct dir_context *ctx) { -int err;const struct NTFS_DE *e;u32 e_size;u32 end =le32_to_cpu (hdr->used);
@@ -354,12 +360,12 @@ static int ntfs_read_hdr(struct ntfs_sb_info *sbi, struct ntfs_inode *ni,for (;; off += e_size) {if (off +sizeof (struct NTFS_DE ) > end) -return -1 ; +return -EINVAL ; e =Add2Ptr (hdr, off); e_size =le16_to_cpu (e->size);if (e_size <sizeof (struct NTFS_DE ) || off + e_size > end) -return -1 ; +return -EINVAL ;if (de_is_last (e))return 0 ;
@@ -369,14 +375,15 @@ static int ntfs_read_hdr(struct ntfs_sb_info *sbi, struct ntfs_inode *ni,continue ;if (le16_to_cpu (e->key_size) <SIZEOF_ATTRIBUTE_FILENAME ) -return -1 ; +return -EINVAL ; ctx->pos = vbo + off;/* Submit the name to the filldir callback. */ - err =ntfs_filldir (sbi, ni, e, name, ctx); -if (err) -return err; +if (!ntfs_dir_emit (sbi, ni, e, name, ctx)) { +/* ctx is full. */ +return +1 ; + } } }
@@ -475,8 +482,6 @@ static int ntfs_readdir(struct file *file, struct dir_context *ctx) vbo = (u64 )bit << index_bits;if (vbo >= i_size) { -ntfs_inode_err (dir,"Looks like your dir is corrupt" ); - ctx->pos = eod; err = -EINVAL ; goto out; }
@@ -499,9 +504,16 @@ static int ntfs_readdir(struct file *file, struct dir_context *ctx)__putname (name);put_indx_node (node); -if (err == -ENOENT ) { +if (err ==1 ) { +/* 'ctx' is full. */ + err =0 ; + }else if (err == -ENOENT ) { err =0 ; ctx->pos = pos; + }else if (err <0 ) { +if (err == -EINVAL ) +ntfs_inode_err (dir,"directory corrupted" ); + ctx->pos = eod; }return err;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 153/214 btrfs: replace BUG_ON with ASSERT in walk_down_proc()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Josef Bacik <[email protected]>
[ Upstream commit 1f9d44c0a12730a24f8bb75c5e1102207413cc9b ]
We have a couple of areas where we check to make sure the tree block is locked before looking up or messing with references. This is old code so it has this as BUG_ON(). Convert this to ASSERT() for developers.
--- fs/btrfs/extent-tree.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/btrfs/extent-tree.c +2 -2
@@ -5086,7 +5086,7 @@ static noinline int walk_down_proc(struct btrfs_trans_handle *trans,if (lookup_info && ((wc->stage ==DROP_REFERENCE && wc->refs[level] !=1 ) || (wc->stage ==UPDATE_BACKREF && !(wc->flags[level] & flag)))) { -BUG_ON (!path->locks[level]); +ASSERT (path->locks[level]); ret = btrfs_lookup_extent_info(trans, fs_info, eb->start, level, 1, &wc->refs[level],
@@ -5110,7 +5110,7 @@ static noinline int walk_down_proc(struct btrfs_trans_handle *trans,/* wc->stage == UPDATE_BACKREF */ if (!(wc->flags[level] & flag)) { -BUG_ON (!path->locks[level]); +ASSERT (path->locks[level]); ret =btrfs_inc_ref (trans, root, eb,1 );BUG_ON (ret);/* -ENOMEM */ ret =btrfs_dec_ref (trans, root, eb,0 );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 154/214 btrfs: clean up our handling of refs == 0 in snapshot delete
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Josef Bacik <[email protected]>
[ Upstream commit b8ccef048354074a548f108e51d0557d6adfd3a3 ]
In reada we BUG_ON(refs == 0), which could be unkind since we aren't holding a lock on the extent leaf and thus could get a transient incorrect answer. In walk_down_proc we also BUG_ON(refs == 0), which could happen if we have extent tree corruption. Change that to return -EUCLEAN. In do_walk_down() we catch this case and handle it correctly, however we return -EIO, which -EUCLEAN is a more appropriate error code. Finally in walk_up_proc we have the same BUG_ON(refs == 0), so convert that to proper error handling. Also adjust the error message so we can actually do something with the information.
--- fs/btrfs/extent-tree.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-)
fs/btrfs/extent-tree.c +23 -5
@@ -5027,7 +5027,15 @@ static noinline void reada_walk_down(struct btrfs_trans_handle *trans,/* We don't care about errors in readahead. */ if (ret <0 )continue ; -BUG_ON (refs ==0 ); + +/* +* This could be racey, it's conceivable that we raced and end +* up with a bogus refs count, if that's the case just skip, if +* we are actually corrupt we will notice when we look up +* everything again with our locks. +*/ +if (refs ==0 ) +continue ;if (wc->stage ==DROP_REFERENCE ) {if (refs ==1 )
@@ -5094,7 +5102,11 @@ static noinline int walk_down_proc(struct btrfs_trans_handle *trans,BUG_ON (ret == -ENOMEM );if (ret)return ret; -BUG_ON (wc->refs[level] ==0 ); +if (unlikely (wc->refs[level] ==0 )) { +btrfs_err (fs_info,"bytenr %llu has 0 references, expect > 0" , + eb->start); +return -EUCLEAN ; + } }if (wc->stage ==DROP_REFERENCE ) {
@@ -5224,8 +5236,9 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans, goto out_unlock;if (unlikely (wc->refs[level -1 ] ==0 )) { -btrfs_err (fs_info,"Missing references." ); - ret = -EIO ; +btrfs_err (fs_info,"bytenr %llu has 0 references, expect > 0" , + bytenr); + ret = -EUCLEAN ; goto out_unlock; } *lookup_info =0 ;
@@ -5426,7 +5439,12 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans, path->locks[level] =0 ;return ret; } -BUG_ON (wc->refs[level] ==0 ); +if (unlikely (wc->refs[level] ==0 )) { +btrfs_tree_unlock_rw (eb, path->locks[level]); +btrfs_err (fs_info,"bytenr %llu has 0 references, expect > 0" , + eb->start); +return -EUCLEAN ; + }if (wc->refs[level] ==1 ) {btrfs_tree_unlock_rw (eb, path->locks[level]); path->locks[level] =0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 155/214 btrfs: replace BUG_ON() with error handling at update_ref_for_cow()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana <[email protected]>
[ Upstream commit b56329a782314fde5b61058e2a25097af7ccb675 ]
Instead of a BUG_ON() just return an error, log an error message and abort the transaction in case we find an extent buffer belonging to the relocation tree that doesn't have the full backref flag set. This is unexpected and should never happen (save for bugs or a potential bad memory).
--- fs/btrfs/ctree.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
fs/btrfs/ctree.c +10 -2
@@ -306,8 +306,16 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, } owner =btrfs_header_owner (buf); -BUG_ON (owner ==BTRFS_TREE_RELOC_OBJECTID && - !(flags &BTRFS_BLOCK_FLAG_FULL_BACKREF )); +if (unlikely (owner ==BTRFS_TREE_RELOC_OBJECTID && + !(flags &BTRFS_BLOCK_FLAG_FULL_BACKREF ))) { +btrfs_crit (fs_info, +"found tree block at bytenr %llu level %d root %llu refs %llu flags %llx without full backref flag set" , + buf->start,btrfs_header_level (buf), +btrfs_root_id (root), refs, flags); + ret = -EUCLEAN ; +btrfs_abort_transaction (trans, ret); +return ret; + }if (refs >1 ) { if ((owner == root->root_key.objectid ||
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 156/214 riscv: set trap vector earlier
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: yang.zhang <[email protected]>
[ Upstream commit 6ad8735994b854b23c824dd6b1dd2126e893a3b4 ]
The exception vector of the booting hart is not set before enabling the mmu and then still points to the value of the previous firmware, typically _start. That makes it hard to debug setup_vm() when bad things happen. So fix that by setting the exception vector earlier.
--- arch/riscv/kernel/head.S | 3 +++ 1 file changed, 3 insertions(+)
arch/riscv/kernel/head.S +3 -0
@@ -309,6 +309,9 @@ clear_bss_done: #else mv a0, s1 #endif /* CONFIG_BUILTIN_DTB */ + /* Set trap vector to spin forever to help debug */ + la a3, .Lsecondary_park + csrw CSR_TVEC, a3 call setup_vm #ifdef CONFIG_MMU la a0, early_pg_dir
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 157/214 PCI: Add missing bridge lock to pci_bus_lock()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Williams <[email protected]>
[ Upstream commit a4e772898f8bf2e7e1cf661a12c60a5612c4afab ]
One of the true positives that the cfg_access_lock lockdep effort identified is this sequence:
WARNING: CPU: 14 PID: 1 at drivers/pci/pci.c:4886 pci_bridge_secondary_bus_reset+0x5d/0x70 RIP: 0010:pci_bridge_secondary_bus_reset+0x5d/0x70 Call Trace: <TASK> ? __warn+0x8c/0x190 ? pci_bridge_secondary_bus_reset+0x5d/0x70 ? report_bug+0x1f8/0x200 ? handle_bug+0x3c/0x70 ? exc_invalid_op+0x18/0x70 ? asm_exc_invalid_op+0x1a/0x20 ? pci_bridge_secondary_bus_reset+0x5d/0x70 pci_reset_bus+0x1d8/0x270 vmd_probe+0x778/0xa10 pci_device_probe+0x95/0x120
Where pci_reset_bus() users are triggering unlocked secondary bus resets. Ironically pci_bus_reset(), several calls down from pci_reset_bus(), uses pci_bus_lock() before issuing the reset which locks everything *but* the bridge itself.
For the same motivation as adding:
bridge = pci_upstream_bridge(dev);
if (bridge)
pci_dev_lock(bridge);to pci_reset_function() for the "bus" and "cxl_bus" reset cases, add pci_dev_lock() for @bus->self to pci_bus_lock().
[bhelgaas: squash in recursive locking deadlock fix from Keith Busch:
https://lore.kernel.org/r/[email protected]]
--- drivers/pci/pci.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-)
drivers/pci/pci.c +21 -14
@@ -5496,10 +5496,12 @@ static void pci_bus_lock(struct pci_bus *bus) {struct pci_dev *dev; +pci_dev_lock (bus->self);list_for_each_entry (dev, &bus->devices, bus_list) { -pci_dev_lock (dev);if (dev->subordinate)pci_bus_lock (dev->subordinate); +else +pci_dev_lock (dev); } }
@@ -5511,8 +5513,10 @@ static void pci_bus_unlock(struct pci_bus *bus)list_for_each_entry (dev, &bus->devices, bus_list) {if (dev->subordinate)pci_bus_unlock (dev->subordinate); -pci_dev_unlock (dev); +else +pci_dev_unlock (dev); } +pci_dev_unlock (bus->self); }/* Return 1 on successful lock, 0 on contention */
@@ -5520,15 +5524,15 @@ static int pci_bus_trylock(struct pci_bus *bus) {struct pci_dev *dev; +if (!pci_dev_trylock (bus->self)) +return 0 ; +list_for_each_entry (dev, &bus->devices, bus_list) { -if (!pci_dev_trylock (dev)) - goto unlock;if (dev->subordinate) { -if (!pci_bus_trylock (dev->subordinate)) { -pci_dev_unlock (dev); +if (!pci_bus_trylock (dev->subordinate)) goto unlock; - } - } + }else if (!pci_dev_trylock (dev)) + goto unlock; }return 1 ;
@@ -5536,8 +5540,10 @@ static int pci_bus_trylock(struct pci_bus *bus)list_for_each_entry_continue_reverse (dev, &bus->devices, bus_list) {if (dev->subordinate)pci_bus_unlock (dev->subordinate); -pci_dev_unlock (dev); +else +pci_dev_unlock (dev); } +pci_dev_unlock (bus->self);return 0 ; }
@@ -5569,9 +5575,10 @@ static void pci_slot_lock(struct pci_slot *slot)list_for_each_entry (dev, &slot->bus->devices, bus_list) {if (!dev->slot || dev->slot != slot)continue ; -pci_dev_lock (dev);if (dev->subordinate)pci_bus_lock (dev->subordinate); +else +pci_dev_lock (dev); } }
@@ -5597,14 +5604,13 @@ static int pci_slot_trylock(struct pci_slot *slot)list_for_each_entry (dev, &slot->bus->devices, bus_list) {if (!dev->slot || dev->slot != slot)continue ; -if (!pci_dev_trylock (dev)) - goto unlock;if (dev->subordinate) {if (!pci_bus_trylock (dev->subordinate)) {pci_dev_unlock (dev); goto unlock; } - } + }else if (!pci_dev_trylock (dev)) + goto unlock; }return 1 ;
@@ -5615,7 +5621,8 @@ static int pci_slot_trylock(struct pci_slot *slot)continue ;if (dev->subordinate)pci_bus_unlock (dev->subordinate); -pci_dev_unlock (dev); +else +pci_dev_unlock (dev); }return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 158/214 net: dpaa: avoid on-stack arrays of NR_CPUS elements
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vladimir Oltean <[email protected]>
[ Upstream commit 555a05d84ca2c587e2d4777006e2c2fb3dfbd91d ]
The dpaa-eth driver is written for PowerPC and Arm SoCs which have 1-24 CPUs. It depends on CONFIG_NR_CPUS having a reasonably small value in Kconfig. Otherwise, there are 2 functions which allocate on-stack arrays of NR_CPUS elements, and these can quickly explode in size, leading to warnings such as:
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c:3280:12: warning:
stack frame size (16664) exceeds limit (2048) in 'dpaa_eth_probe' [-Wframe-larger-than]
The problem is twofold:
- Reducing the array size to the boot-time num_possible_cpus() (rather than the compile-time NR_CPUS) creates a variable-length array, which should be avoided in the Linux kernel.
- Using NR_CPUS as an array size makes the driver blow up in stack consumption with generic, as opposed to hand-crafted, .config files.
A simple solution is to use dynamic allocation for num_possible_cpus() elements (aka a small number determined at runtime).
--- .../net/ethernet/freescale/dpaa/dpaa_eth.c | 20 ++++++++++++++----- .../ethernet/freescale/dpaa/dpaa_ethtool.c | 10 +++++++++- 2 files changed, 24 insertions(+), 6 deletions(-)
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +15 -5
@@ -910,14 +910,18 @@ static inline void dpaa_setup_egress(const struct dpaa_priv *priv, } } -static void dpaa_fq_setup (struct dpaa_priv *priv, -const struct dpaa_fq_cbs *fq_cbs, -struct fman_port *tx_port) +static int dpaa_fq_setup (struct dpaa_priv *priv, +const struct dpaa_fq_cbs *fq_cbs, +struct fman_port *tx_port) {int egress_cnt =0 , conf_cnt =0 , num_portals =0 , portal_cnt =0 , cpu;const cpumask_t *affine_cpus =qman_affine_cpus (); -u16 channels[NR_CPUS ];struct dpaa_fq *fq; +u16 *channels; + + channels =kcalloc (num_possible_cpus (),sizeof (u16),GFP_KERNEL ); +if (!channels) +return -ENOMEM ;for_each_cpu_and (cpu, affine_cpus, cpu_online_mask) channels[num_portals++] =qman_affine_channel (cpu);
@@ -976,6 +980,10 @@ static void dpaa_fq_setup(struct dpaa_priv *priv,break ; } } + +kfree (channels); + +return 0 ; } static inline int dpaa_tx_fq_to_id(const struct dpaa_priv *priv,
@@ -3444,7 +3452,9 @@ static int dpaa_eth_probe(struct platform_device *pdev)*/ dpaa_eth_add_channel (priv->channel, &pdev->dev); -dpaa_fq_setup (priv, &dpaa_fq_cbs, priv->mac_dev->port[TX ]); + err =dpaa_fq_setup (priv, &dpaa_fq_cbs, priv->mac_dev->port[TX ]); +if (err) + goto free_dpaa_bps;/* Create a congestion group for this netdev, with * dynamically-allocated CGR ID.
drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c +9 -1
@@ -541,12 +541,16 @@ static int dpaa_set_coalesce(struct net_device *dev, struct netlink_ext_ack *extack) {const cpumask_t *cpus =qman_affine_cpus (); -bool needs_revert[NR_CPUS ] = {false};struct qman_portal *portal;u32 period, prev_period;u8 thresh, prev_thresh; +bool *needs_revert;int cpu, res; + needs_revert =kcalloc (num_possible_cpus (),sizeof (bool ),GFP_KERNEL ); +if (!needs_revert) +return -ENOMEM ; + period = c->rx_coalesce_usecs; thresh = c->rx_max_coalesced_frames;
@@ -569,6 +573,8 @@ static int dpaa_set_coalesce(struct net_device *dev, needs_revert[cpu] = true; } +kfree (needs_revert); +return 0 ; revert_values:
@@ -582,6 +588,8 @@ static int dpaa_set_coalesce(struct net_device *dev,qman_dqrr_set_ithresh (portal, prev_thresh); } +kfree (needs_revert); +return res; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 159/214 i3c: mipi-i3c-hci: Error out instead on BUG_ON() in IBI DMA setup
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jarkko Nikula <[email protected]>
[ Upstream commit 8a2be2f1db268ec735419e53ef04ca039fc027dc ]
Definitely condition dma_get_cache_alignment * defined value > 256 during driver initialization is not reason to BUG_ON(). Turn that to graceful error out with -EINVAL.
--- drivers/i3c/master/mipi-i3c-hci/dma.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/i3c/master/mipi-i3c-hci/dma.c +4 -1
@@ -291,7 +291,10 @@ static int hci_dma_init(struct i3c_hci *hci) rh->ibi_chunk_sz =dma_get_cache_alignment (); rh->ibi_chunk_sz *=IBI_CHUNK_CACHELINES ; -BUG_ON (rh->ibi_chunk_sz >256 ); +if (rh->ibi_chunk_sz >256 ) { + ret = -EINVAL ; + goto err_out; + } ibi_status_ring_sz = rh->ibi_status_sz * rh->ibi_status_entries; ibi_data_ring_sz = rh->ibi_chunk_sz * rh->ibi_chunks_total;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 160/214 kselftests: dmabuf-heaps: Ensure the driver name is null-terminated
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zenghui Yu <[email protected]>
[ Upstream commit 291e4baf70019f17a81b7b47aeb186b27d222159 ]
Even if a vgem device is configured in, we will skip the import_vgem_fd() test almost every time.
TAP version 13
1..11
# Testing heap: system
# =======================================
# Testing allocation and importing:
ok 1 # SKIP Could not open vgem -1
The problem is that we use the DRM_IOCTL_VERSION ioctl to query the driver version information but leave the name field a non-null-terminated string. Terminate it properly to actually test against the vgem device.
While at it, let's check the length of the driver name is exactly 4 bytes and return early otherwise (in case there is a name like "vgemfoo" that gets converted to "vgem\0" unexpectedly).
--- tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c +3 -1
@@ -29,9 +29,11 @@ static int check_vgem(int fd) version.name = name; ret =ioctl (fd,DRM_IOCTL_VERSION , &version); -if (ret) +if (ret || version.name_len !=4 )return 0 ; + name[4 ] ='\0' ; +return !strcmp (name,"vgem" ); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 161/214 btrfs: initialize location to fix -Wmaybe-uninitialized in btrfs_lookup_dentry()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Sterba <[email protected]>
[ Upstream commit b8e947e9f64cac9df85a07672b658df5b2bcff07 ]
Some arch + compiler combinations report a potentially unused variable location in btrfs_lookup_dentry(). This is a false alert as the variable is passed by value and always valid or there's an error. The compilers cannot probably reason about that although btrfs_inode_by_name() is in the same file.
Quoted 1 line
+ /kisskb/src/fs/btrfs/inode.c: error: 'location.objectid' may be used
+uninitialized in this function [-Werror=maybe-uninitialized]: => 5603:9
Quoted 1 line
+ /kisskb/src/fs/btrfs/inode.c: error: 'location.type' may be used
+uninitialized in this function [-Werror=maybe-uninitialized]: => 5674:5
m68k-gcc8/m68k-allmodconfig
mips-gcc8/mips-allmodconfig
powerpc-gcc5/powerpc-all{mod,yes}config
powerpc-gcc5/ppc64_defconfig
Initialize it to zero, this should fix the warnings and won't change the behaviour as btrfs_inode_by_name() accepts only a root or inode item types, otherwise returns an error.
--- fs/btrfs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/btrfs/inode.c +1 -1
@@ -6048,7 +6048,7 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)struct inode *inode;struct btrfs_root *root =BTRFS_I (dir)->root;struct btrfs_root *sub_root = root; -struct btrfs_key location; +struct btrfs_key location = {0 };u8 di_type =0 ;int ret =0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 162/214 s390/vmlinux.lds.S: Move ro_after_init section behind rodata section
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Heiko Carstens <[email protected]>
[ Upstream commit 75c10d5377d8821efafed32e4d72068d9c1f8ec0 ]
The .data.rel.ro and .got section were added between the rodata and ro_after_init data section, which adds an RW mapping in between all RO mapping of the kernel image:
---[ Kernel Image Start ]---
0x000003ffe0000000-0x000003ffe0e00000 14M PMD RO X
0x000003ffe0e00000-0x000003ffe0ec7000 796K PTE RO X
0x000003ffe0ec7000-0x000003ffe0f00000 228K PTE RO NX
0x000003ffe0f00000-0x000003ffe1300000 4M PMD RO NX
0x000003ffe1300000-0x000003ffe1331000 196K PTE RO NX 0x000003ffe1331000-0x000003ffe13b3000 520K PTE RW NX <--- 0x000003ffe13b3000-0x000003ffe13d5000 136K PTE RO NX 0x000003ffe13d5000-0x000003ffe1400000 172K PTE RW NX 0x000003ffe1400000-0x000003ffe1500000 1M PMD RW NX 0x000003ffe1500000-0x000003ffe1700000 2M PTE RW NX 0x000003ffe1700000-0x000003ffe1800000 1M PMD RW NX
0x000003ffe1800000-0x000003ffe187e000 504K PTE RW NX
---[ Kernel Image End ]---
Move the ro_after_init data section again right behind the rodata section to prevent interleaving RO and RW mappings:
---[ Kernel Image Start ]---
0x000003ffe0000000-0x000003ffe0e00000 14M PMD RO X
0x000003ffe0e00000-0x000003ffe0ec7000 796K PTE RO X
0x000003ffe0ec7000-0x000003ffe0f00000 228K PTE RO NX
0x000003ffe0f00000-0x000003ffe1300000 4M PMD RO NX
0x000003ffe1300000-0x000003ffe1353000 332K PTE RO NX
0x000003ffe1353000-0x000003ffe1400000 692K PTE RW NX
0x000003ffe1400000-0x000003ffe1500000 1M PMD RW NX 0x000003ffe1500000-0x000003ffe1700000 2M PTE RW NX 0x000003ffe1700000-0x000003ffe1800000 1M PMD RW NX
0x000003ffe1800000-0x000003ffe187e000 504K PTE RW NX
---[ Kernel Image End ]---
--- arch/s390/kernel/vmlinux.lds.S | 9 +++++++++ 1 file changed, 9 insertions(+)
arch/s390/kernel/vmlinux.lds.S +9 -0
@@ -72,6 +72,15 @@ SECTIONS . = ALIGN(PAGE_SIZE); __end_ro_after_init = .; + .data.rel.ro : { + *(.data.rel.ro .data.rel.ro.*) + } + .got : { + __got_start = .; + *(.got) + __got_end = .; + } + RW_DATA(0x100, PAGE_SIZE, THREAD_SIZE) BOOT_DATA_PRESERVED
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 163/214 HID: cougar: fix slab-out-of-bounds Read in cougar_report_fixup
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Camila Alvarez <[email protected]>
[ Upstream commit a6e9c391d45b5865b61e569146304cff72821a5d ]
report_fixup for the Cougar 500k Gaming Keyboard was not verifying that the report descriptor size was correct before accessing it
--- drivers/hid/hid-cougar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/hid/hid-cougar.c +1 -1
@@ -106,7 +106,7 @@ static void cougar_fix_g6_mapping(void)static __u8 *cougar_report_fixup (struct hid_device *hdev,__u8 *rdesc,unsigned int *rsize) { -if (rdesc[2 ] ==0x09 && rdesc[3 ] ==0x02 && +if (*rsize >=117 && rdesc[2 ] ==0x09 && rdesc[3 ] ==0x02 && (rdesc[115 ] | rdesc[116 ] <<8 ) >=HID_MAX_USAGES ) {hid_info (hdev,"usage count exceeds max: fixing up report descriptor\n" );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 164/214 HID: amd_sfh: free driver_data after destroying hid device
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Olivier Sobrie <[email protected]>
[ Upstream commit 97155021ae17b86985121b33cf8098bcde00d497 ]
HID driver callbacks aren't called anymore once hid_destroy_device() has been called. Hence, hid driver_data should be freed only after the hid_destroy_device() function returned as driver_data is used in several callbacks.
I observed a crash with kernel 6.10.0 on my T14s Gen 3, after enabling KASAN to debug memory allocation, I got this output:
[ 13.050438] ================================================================== [ 13.054060] BUG: KASAN: slab-use-after-free in amd_sfh_get_report+0x3ec/0x530 [amd_sfh] [ 13.054809] psmouse serio1: trackpoint: Synaptics TrackPoint firmware: 0x02, buttons: 3/3 [ 13.056432] Read of size 8 at addr ffff88813152f408 by task (udev-worker)/479
[ 13.060970] CPU: 5 PID: 479 Comm: (udev-worker) Not tainted 6.10.0-arch1-2 #1 893bb55d7f0073f25c46adbb49eb3785fefd74b0 [ 13.063978] Hardware name: LENOVO 21CQCTO1WW/21CQCTO1WW, BIOS R22ET70W (1.40 ) 03/21/2024 [ 13.067860] Call Trace: [ 13.069383] input: TPPS/2 Synaptics TrackPoint as /devices/platform/i8042/serio1/input/input8 [ 13.071486] <TASK> [ 13.071492] dump_stack_lvl+0x5d/0x80 [ 13.074870] snd_hda_intel 0000:33:00.6: enabling device (0000 -> 0002) [ 13.078296] ? amd_sfh_get_report+0x3ec/0x530 [amd_sfh 05f43221435b5205f734cd9da29399130f398a38] [ 13.082199] print_report+0x174/0x505 [ 13.085776] ? __pfx__raw_spin_lock_irqsave+0x10/0x10 [ 13.089367] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.093255] ? amd_sfh_get_report+0x3ec/0x530 [amd_sfh 05f43221435b5205f734cd9da29399130f398a38] [ 13.097464] kasan_report+0xc8/0x150 [ 13.101461] ? amd_sfh_get_report+0x3ec/0x530 [amd_sfh 05f43221435b5205f734cd9da29399130f398a38] [ 13.105802] amd_sfh_get_report+0x3ec/0x530 [amd_sfh 05f43221435b5205f734cd9da29399130f398a38] [ 13.110303] amdtp_hid_request+0xb8/0x110 [amd_sfh 05f43221435b5205f734cd9da29399130f398a38] [ 13.114879] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.119450] sensor_hub_get_feature+0x1d3/0x540 [hid_sensor_hub 3f13be3016ff415bea03008d45d99da837ee3082] [ 13.124097] hid_sensor_parse_common_attributes+0x4d0/0xad0 [hid_sensor_iio_common c3a5cbe93969c28b122609768bbe23efe52eb8f5] [ 13.127404] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.131925] ? __pfx_hid_sensor_parse_common_attributes+0x10/0x10 [hid_sensor_iio_common c3a5cbe93969c28b122609768bbe23efe52eb8f5] [ 13.136455] ? _raw_spin_lock_irqsave+0x96/0xf0 [ 13.140197] ? __pfx__raw_spin_lock_irqsave+0x10/0x10 [ 13.143602] ? devm_iio_device_alloc+0x34/0x50 [industrialio 3d261d5e5765625d2b052be40e526d62b1d2123b] [ 13.147234] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.150446] ? __devm_add_action+0x167/0x1d0 [ 13.155061] hid_gyro_3d_probe+0x120/0x7f0 [hid_sensor_gyro_3d 63da36a143b775846ab2dbb86c343b401b5e3172] [ 13.158581] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.161814] platform_probe+0xa2/0x150 [ 13.165029] really_probe+0x1e3/0x8a0 [ 13.168243] __driver_probe_device+0x18c/0x370 [ 13.171500] driver_probe_device+0x4a/0x120 [ 13.175000] __driver_attach+0x190/0x4a0 [ 13.178521] ? __pfx___driver_attach+0x10/0x10 [ 13.181771] bus_for_each_dev+0x106/0x180 [ 13.185033] ? __pfx__raw_spin_lock+0x10/0x10 [ 13.188229] ? __pfx_bus_for_each_dev+0x10/0x10 [ 13.191446] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.194382] bus_add_driver+0x29e/0x4d0 [ 13.197328] driver_register+0x1a5/0x360 [ 13.200283] ? __pfx_hid_gyro_3d_platform_driver_init+0x10/0x10 [hid_sensor_gyro_3d 63da36a143b775846ab2dbb86c343b401b5e3172] [ 13.203362] do_one_initcall+0xa7/0x380 [ 13.206432] ? __pfx_do_one_initcall+0x10/0x10 [ 13.210175] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.213211] ? kasan_unpoison+0x44/0x70 [ 13.216688] do_init_module+0x238/0x750 [ 13.219696] load_module+0x5011/0x6af0 [ 13.223096] ? kasan_save_stack+0x30/0x50 [ 13.226743] ? kasan_save_track+0x14/0x30 [ 13.230080] ? kasan_save_free_info+0x3b/0x60 [ 13.233323] ? poison_slab_object+0x109/0x180 [ 13.236778] ? __pfx_load_module+0x10/0x10 [ 13.239703] ? poison_slab_object+0x109/0x180 [ 13.243070] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.245924] ? init_module_from_file+0x13d/0x150 [ 13.248745] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.251503] ? init_module_from_file+0xdf/0x150 [ 13.254198] init_module_from_file+0xdf/0x150 [ 13.256826] ? __pfx_init_module_from_file+0x10/0x10 [ 13.259428] ? kasan_save_track+0x14/0x30 [ 13.261959] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.264471] ? kasan_save_free_info+0x3b/0x60 [ 13.267026] ? poison_slab_object+0x109/0x180 [ 13.269494] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.271949] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.274324] ? _raw_spin_lock+0x85/0xe0 [ 13.276671] ? __pfx__raw_spin_lock+0x10/0x10 [ 13.278963] ? __rseq_handle_notify_resume+0x1a6/0xad0 [ 13.281193] idempotent_init_module+0x23b/0x650 [ 13.283420] ? __pfx_idempotent_init_module+0x10/0x10 [ 13.285619] ? __pfx___seccomp_filter+0x10/0x10 [ 13.287714] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.289828] ? __fget_light+0x57/0x420 [ 13.291870] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.293880] ? security_capable+0x74/0xb0 [ 13.295820] __x64_sys_finit_module+0xbe/0x130 [ 13.297874] do_syscall_64+0x82/0x190 [ 13.299898] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.301905] ? irqtime_account_irq+0x3d/0x1f0 [ 13.303877] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.305753] ? __irq_exit_rcu+0x4e/0x130 [ 13.307577] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.309489] entry_SYSCALL_64_after_hwframe+0x76/0x7e [ 13.311371] RIP: 0033:0x7a21f96ade9d [ 13.313234] Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 63 de 0c 00 f7 d8 64 89 01 48 [ 13.317051] RSP: 002b:00007ffeae934e78 EFLAGS: 00000246 ORIG_RAX: 0000000000000139 [ 13.319024] RAX: ffffffffffffffda RBX: 00005987276bfcf0 RCX: 00007a21f96ade9d [ 13.321100] RDX: 0000000000000004 RSI: 00007a21f8eda376 RDI: 000000000000001c [ 13.323314] RBP: 00007a21f8eda376 R08: 0000000000000001 R09: 00007ffeae934ec0 [ 13.325505] R10: 0000000000000050 R11: 0000000000000246 R12: 0000000000020000 [ 13.327637] R13: 00005987276c1250 R14: 0000000000000000 R15: 00005987276c4530 [ 13.329737] </TASK>
[ 13.333945] Allocated by task 139: [ 13.336111] kasan_save_stack+0x30/0x50 [ 13.336121] kasan_save_track+0x14/0x30 [ 13.336125] __kasan_kmalloc+0xaa/0xb0 [ 13.336129] amdtp_hid_probe+0xb1/0x440 [amd_sfh] [ 13.336138] amd_sfh_hid_client_init+0xb8a/0x10f0 [amd_sfh] [ 13.336144] sfh_init_work+0x47/0x120 [amd_sfh] [ 13.336150] process_one_work+0x673/0xeb0 [ 13.336155] worker_thread+0x795/0x1250 [ 13.336160] kthread+0x290/0x350 [ 13.336164] ret_from_fork+0x34/0x70 [ 13.336169] ret_from_fork_asm+0x1a/0x30
[ 13.338175] Freed by task 139: [ 13.340064] kasan_save_stack+0x30/0x50 [ 13.340072] kasan_save_track+0x14/0x30 [ 13.340076] kasan_save_free_info+0x3b/0x60 [ 13.340081] poison_slab_object+0x109/0x180 [ 13.340085] __kasan_slab_free+0x32/0x50 [ 13.340089] kfree+0xe5/0x310 [ 13.340094] amdtp_hid_remove+0xb2/0x160 [amd_sfh] [ 13.340102] amd_sfh_hid_client_deinit+0x324/0x640 [amd_sfh] [ 13.340107] amd_sfh_hid_client_init+0x94a/0x10f0 [amd_sfh] [ 13.340113] sfh_init_work+0x47/0x120 [amd_sfh] [ 13.340118] process_one_work+0x673/0xeb0 [ 13.340123] worker_thread+0x795/0x1250 [ 13.340127] kthread+0x290/0x350 [ 13.340132] ret_from_fork+0x34/0x70 [ 13.340136] ret_from_fork_asm+0x1a/0x30
[ 13.342482] The buggy address belongs to the object at ffff88813152f400
which belongs to the cache kmalloc-64 of size 64
[ 13.347357] The buggy address is located 8 bytes inside of
freed 64-byte region [ffff88813152f400, ffff88813152f440)[ 13.347367] The buggy address belongs to the physical page: [ 13.355409] page: refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x13152f [ 13.355416] anon flags: 0x2ffff8000000000(node=0|zone=2|lastcpupid=0x1ffff) [ 13.355423] page_type: 0xffffefff(slab) [ 13.355429] raw: 02ffff8000000000 ffff8881000428c0 ffffea0004c43a00 0000000000000005 [ 13.355435] raw: 0000000000000000 0000000000200020 00000001ffffefff 0000000000000000 [ 13.355439] page dumped because: kasan: bad access detected
[ 13.357295] Memory state around the buggy address: [ 13.357299] ffff88813152f300: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc [ 13.357303] ffff88813152f380: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc [ 13.357306] >ffff88813152f400: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc [ 13.357309] ^ [ 13.357311] ffff88813152f480: 00 00 00 00 00 fc fc fc fc fc fc fc fc fc fc fc [ 13.357315] ffff88813152f500: 00 00 00 00 00 00 00 06 fc fc fc fc fc fc fc fc [ 13.357318] ================================================================== [ 13.357405] Disabling lock debugging due to kernel taint [ 13.383534] Oops: general protection fault, probably for non-canonical address 0xe0a1bc4140000013: 0000 [#1] PREEMPT SMP KASAN NOPTI [ 13.383544] KASAN: maybe wild-memory-access in range [0x050e020a00000098-0x050e020a0000009f] [ 13.383551] CPU: 3 PID: 479 Comm: (udev-worker) Tainted: G B 6.10.0-arch1-2 #1 893bb55d7f0073f25c46adbb49eb3785fefd74b0 [ 13.383561] Hardware name: LENOVO 21CQCTO1WW/21CQCTO1WW, BIOS R22ET70W (1.40 ) 03/21/2024 [ 13.383565] RIP: 0010:amd_sfh_get_report+0x81/0x530 [amd_sfh] [ 13.383580] Code: 89 fa 48 c1 ea 03 80 3c 02 00 0f 85 78 03 00 00 48 b8 00 00 00 00 00 fc ff df 4c 8b 63 08 49 8d 7c 24 10 48 89 fa 48 c1 ea 03 <0f> b6 04 02 84 c0 74 08 3c 03 0f 8e 1a 03 00 00 45 8b 74 24 10 45 [ 13.383585] RSP: 0018:ffff8881261f7388 EFLAGS: 00010212 [ 13.383592] RAX: dffffc0000000000 RBX: ffff88813152f400 RCX: 0000000000000002 [ 13.383597] RDX: 00a1c04140000013 RSI: 0000000000000008 RDI: 050e020a0000009b [ 13.383600] RBP: ffff88814d010000 R08: 0000000000000002 R09: fffffbfff3ddb8c0 [ 13.383604] R10: ffffffff9eedc607 R11: ffff88810ce98000 R12: 050e020a0000008b [ 13.383607] R13: ffff88814d010000 R14: dffffc0000000000 R15: 0000000000000004 [ 13.383611] FS: 00007a21f94d0880(0000) GS:ffff8887e7d80000(0000) knlGS:0000000000000000 [ 13.383615] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 13.383618] CR2: 00007e0014c438f0 CR3: 000000012614c000 CR4: 0000000000f50ef0 [ 13.383622] PKRU: 55555554 [ 13.383625] Call Trace: [ 13.383629] <TASK> [ 13.383632] ? __die_body.cold+0x19/0x27 [ 13.383644] ? die_addr+0x46/0x70 [ 13.383652] ? exc_general_protection+0x150/0x240 [ 13.383664] ? asm_exc_general_protection+0x26/0x30 [ 13.383674] ? amd_sfh_get_report+0x81/0x530 [amd_sfh 05f43221435b5205f734cd9da29399130f398a38] [ 13.383686] ? amd_sfh_get_report+0x3ec/0x530 [amd_sfh 05f43221435b5205f734cd9da29399130f398a38] [ 13.383697] amdtp_hid_request+0xb8/0x110 [amd_sfh 05f43221435b5205f734cd9da29399130f398a38] [ 13.383706] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.383713] sensor_hub_get_feature+0x1d3/0x540 [hid_sensor_hub 3f13be3016ff415bea03008d45d99da837ee3082] [ 13.383727] hid_sensor_parse_common_attributes+0x4d0/0xad0 [hid_sensor_iio_common c3a5cbe93969c28b122609768bbe23efe52eb8f5] [ 13.383739] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.383745] ? __pfx_hid_sensor_parse_common_attributes+0x10/0x10 [hid_sensor_iio_common c3a5cbe93969c28b122609768bbe23efe52eb8f5] [ 13.383753] ? _raw_spin_lock_irqsave+0x96/0xf0 [ 13.383762] ? __pfx__raw_spin_lock_irqsave+0x10/0x10 [ 13.383768] ? devm_iio_device_alloc+0x34/0x50 [industrialio 3d261d5e5765625d2b052be40e526d62b1d2123b] [ 13.383790] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.383795] ? __devm_add_action+0x167/0x1d0 [ 13.383806] hid_gyro_3d_probe+0x120/0x7f0 [hid_sensor_gyro_3d 63da36a143b775846ab2dbb86c343b401b5e3172] [ 13.383818] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.383826] platform_probe+0xa2/0x150 [ 13.383832] really_probe+0x1e3/0x8a0 [ 13.383838] __driver_probe_device+0x18c/0x370 [ 13.383844] driver_probe_device+0x4a/0x120 [ 13.383851] __driver_attach+0x190/0x4a0 [ 13.383857] ? __pfx___driver_attach+0x10/0x10 [ 13.383863] bus_for_each_dev+0x106/0x180 [ 13.383868] ? __pfx__raw_spin_lock+0x10/0x10 [ 13.383874] ? __pfx_bus_for_each_dev+0x10/0x10 [ 13.383880] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.383887] bus_add_driver+0x29e/0x4d0 [ 13.383895] driver_register+0x1a5/0x360 [ 13.383902] ? __pfx_hid_gyro_3d_platform_driver_init+0x10/0x10 [hid_sensor_gyro_3d 63da36a143b775846ab2dbb86c343b401b5e3172] [ 13.383910] do_one_initcall+0xa7/0x380 [ 13.383919] ? __pfx_do_one_initcall+0x10/0x10 [ 13.383927] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.383933] ? kasan_unpoison+0x44/0x70 [ 13.383943] do_init_module+0x238/0x750 [ 13.383955] load_module+0x5011/0x6af0 [ 13.383962] ? kasan_save_stack+0x30/0x50 [ 13.383968] ? kasan_save_track+0x14/0x30 [ 13.383973] ? kasan_save_free_info+0x3b/0x60 [ 13.383980] ? poison_slab_object+0x109/0x180 [ 13.383993] ? __pfx_load_module+0x10/0x10 [ 13.384007] ? poison_slab_object+0x109/0x180 [ 13.384012] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.384018] ? init_module_from_file+0x13d/0x150 [ 13.384025] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.384032] ? init_module_from_file+0xdf/0x150 [ 13.384037] init_module_from_file+0xdf/0x150 [ 13.384044] ? __pfx_init_module_from_file+0x10/0x10 [ 13.384050] ? kasan_save_track+0x14/0x30 [ 13.384055] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.384060] ? kasan_save_free_info+0x3b/0x60 [ 13.384066] ? poison_slab_object+0x109/0x180 [ 13.384071] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.384080] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.384085] ? _raw_spin_lock+0x85/0xe0 [ 13.384091] ? __pfx__raw_spin_lock+0x10/0x10 [ 13.384096] ? __rseq_handle_notify_resume+0x1a6/0xad0 [ 13.384106] idempotent_init_module+0x23b/0x650 [ 13.384114] ? __pfx_idempotent_init_module+0x10/0x10 [ 13.384120] ? __pfx___seccomp_filter+0x10/0x10 [ 13.384129] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.384135] ? __fget_light+0x57/0x420 [ 13.384142] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.384147] ? security_capable+0x74/0xb0 [ 13.384157] __x64_sys_finit_module+0xbe/0x130 [ 13.384164] do_syscall_64+0x82/0x190 [ 13.384174] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.384179] ? irqtime_account_irq+0x3d/0x1f0 [ 13.384188] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.384193] ? __irq_exit_rcu+0x4e/0x130 [ 13.384201] ? srso_alias_return_thunk+0x5/0xfbef5 [ 13.384206] entry_SYSCALL_64_after_hwframe+0x76/0x7e [ 13.384212] RIP: 0033:0x7a21f96ade9d [ 13.384263] Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 63 de 0c 00 f7 d8 64 89 01 48 [ 13.384267] RSP: 002b:00007ffeae934e78 EFLAGS: 00000246 ORIG_RAX: 0000000000000139 [ 13.384273] RAX: ffffffffffffffda RBX: 00005987276bfcf0 RCX: 00007a21f96ade9d [ 13.384277] RDX: 0000000000000004 RSI: 00007a21f8eda376 RDI: 000000000000001c [ 13.384280] RBP: 00007a21f8eda376 R08: 0000000000000001 R09: 00007ffeae934ec0 [ 13.384284] R10: 0000000000000050 R11: 0000000000000246 R12: 0000000000020000 [ 13.384288] R13: 00005987276c1250 R14: 0000000000000000 R15: 00005987276c4530 [ 13.384297] </TASK> [ 13.384299] Modules linked in: soundwire_amd(+) hid_sensor_gyro_3d(+) hid_sensor_magn_3d hid_sensor_accel_3d soundwire_generic_allocation amdxcp hid_sensor_trigger drm_exec industrialio_triggered_buffer soundwire_bus gpu_sched kvm_amd kfifo_buf qmi_helpers joydev drm_buddy hid_sensor_iio_common mousedev snd_soc_core industrialio i2c_algo_bit mac80211 snd_compress drm_suballoc_helper kvm snd_hda_intel drm_ttm_helper ac97_bus snd_pcm_dmaengine snd_intel_dspcfg ttm thinkpad_acpi(+) snd_intel_sdw_acpi hid_sensor_hub snd_rpl_pci_acp6x drm_display_helper snd_hda_codec hid_multitouch libarc4 snd_acp_pci platform_profile think_lmi(+) hid_generic firmware_attributes_class wmi_bmof cec snd_acp_legacy_common sparse_keymap rapl snd_hda_core psmouse cfg80211 pcspkr snd_pci_acp6x snd_hwdep video snd_pcm snd_pci_acp5x snd_timer snd_rn_pci_acp3x ucsi_acpi snd_acp_config snd sp5100_tco rfkill snd_soc_acpi typec_ucsi thunderbolt amd_sfh k10temp mhi soundcore i2c_piix4 snd_pci_acp3x typec i2c_hid_acpi roles i2c_hid wmi acpi_tad amd_pmc [ 13.384454] mac_hid i2c_dev crypto_user loop nfnetlink zram ip_tables x_tables dm_crypt cbc encrypted_keys trusted asn1_encoder tee dm_mod crct10dif_pclmul crc32_pclmul polyval_clmulni polyval_generic gf128mul ghash_clmulni_intel serio_raw sha512_ssse3 atkbd sha256_ssse3 libps2 sha1_ssse3 vivaldi_fmap nvme aesni_intel crypto_simd nvme_core cryptd ccp xhci_pci i8042 nvme_auth xhci_pci_renesas serio vfat fat btrfs blake2b_generic libcrc32c crc32c_generic crc32c_intel xor raid6_pq [ 13.384552] ---[ end trace 0000000000000000 ]---
KASAN reports a use-after-free of hid->driver_data in function amd_sfh_get_report(). The backtrace indicates that the function is called by amdtp_hid_request() which is one of the callbacks of hid device. The current make sure that driver_data is freed only once hid_destroy_device() returned.
Note that I observed the crash both on v6.9.9 and v6.10.0. The code seems to be as it was from the early days of the driver.
--- drivers/hid/amd-sfh-hid/amd_sfh_hid.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/hid/amd-sfh-hid/amd_sfh_hid.c +3 -1
@@ -164,11 +164,13 @@ int amdtp_hid_probe(u32 cur_hid_dev, struct amdtp_cl_data *cli_data)void amdtp_hid_remove (struct amdtp_cl_data *cli_data) {int i; +struct amdtp_hid_data *hid_data;for (i =0 ; i < cli_data->num_hid_devices; ++i) {if (cli_data->hid_sensor_hubs[i]) { -kfree (cli_data->hid_sensor_hubs[i]->driver_data); + hid_data = cli_data->hid_sensor_hubs[i]->driver_data;hid_destroy_device (cli_data->hid_sensor_hubs[i]); +kfree (hid_data); cli_data->hid_sensor_hubs[i] =NULL ; } }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 165/214 Input: uinput - reject requests with unreasonable number of slots
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <[email protected]>
[ Upstream commit 206f533a0a7c683982af473079c4111f4a0f9f5e ]
From: Dmitry Torokhov <[email protected]>
When exercising uinput interface syzkaller may try setting up device with a really large number of slots, which causes memory allocation failure in input_mt_init_slots(). While this allocation failure is handled properly and request is rejected, it results in syzkaller reports. Additionally, such request may put undue burden on the system which will try to free a lot of memory for a bogus request.
Fix it by limiting allowed number of slots to 100. This can easily be extended if we see devices that can track more than 100 contacts.
--- drivers/input/misc/uinput.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
drivers/input/misc/uinput.c +14 -0
@@ -416,6 +416,20 @@ static int uinput_validate_absinfo(struct input_dev *dev, unsigned int code,return -EINVAL ; } +/* +* Limit number of contacts to a reasonable value (100). This +* ensures that we need less than 2 pages for struct input_mt +* (we are not using in-kernel slot assignment so not going to +* allocate memory for the "red" table), and we should have no +* trouble getting this much memory. +*/ +if (code ==ABS_MT_SLOT && max >99 ) { +printk (KERN_DEBUG +"%s: unreasonably large number of slots requested: %d\n" , +UINPUT_NAME , max); +return -EINVAL ; + } +return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 166/214 usbnet: ipheth: race between ipheth_close and error handling
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oliver Neukum <[email protected]>
[ Upstream commit e5876b088ba03a62124266fa20d00e65533c7269 ]
ipheth_sndbulk_callback() can submit carrier_work as a part of its error handling. That means that the driver must make sure that the work is cancelled after it has made sure that no more URB can terminate with an error condition.
Hence the order of actions in ipheth_close() needs to be inverted.
--- drivers/net/usb/ipheth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/usb/ipheth.c +1 -1
@@ -353,8 +353,8 @@ static int ipheth_close(struct net_device *net) {struct ipheth_device *dev =netdev_priv (net); -cancel_delayed_work_sync (&dev->carrier_work);netif_stop_queue (net); +cancel_delayed_work_sync (&dev->carrier_work);return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 167/214 Squashfs: sanity check symbolic link size
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Phillip Lougher <[email protected]>
[ Upstream commit 810ee43d9cd245d138a2733d87a24858a23f577d ]
Syzkiller reports a "KMSAN: uninit-value in pick_link" bug.
This is caused by an uninitialised page, which is ultimately caused by a corrupted symbolic link size read from disk.
The reason why the corrupted symlink size causes an uninitialised page is due to the following sequence of events:
1. squashfs_read_inode() is called to read the symbolic link from disk. This assigns the corrupted value 3875536935 to inode->i_size.
2. Later squashfs_symlink_read_folio() is called, which assigns this corrupted value to the length variable, which being a signed int, overflows producing a negative number.
3. The following loop that fills in the page contents checks that the copied bytes is less than length, which being negative means the loop is skipped, producing an uninitialised page.
This patch adds a sanity check which checks that the symbolic link size is not larger than expected.
--
V2: fix spelling mistake.
--- fs/squashfs/inode.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
fs/squashfs/inode.c +6 -1
@@ -276,8 +276,13 @@ int squashfs_read_inode(struct inode *inode, long long ino)if (err <0 ) goto failed_read; -set_nlink (inode,le32_to_cpu (sqsh_ino->nlink)); inode->i_size =le32_to_cpu (sqsh_ino->symlink_size); +if (inode->i_size >PAGE_SIZE ) { +ERROR ("Corrupted symlink\n" ); +return -EINVAL ; + } + +set_nlink (inode,le32_to_cpu (sqsh_ino->nlink)); inode->i_op = &squashfs_symlink_inode_ops;inode_nohighmem (inode); inode->i_data.a_ops = &squashfs_symlink_aops;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 168/214 of/irq: Prevent device address out-of-bounds read in interrupt map walk
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefan Wiehler <[email protected]>
[ Upstream commit b739dffa5d570b411d4bdf4bb9b8dfd6b7d72305 ]
When of_irq_parse_raw() is invoked with a device address smaller than the interrupt parent node (from #address-cells property), KASAN detects the following out-of-bounds read when populating the initial match table (dyndbg="func of_irq_parse_* +p"):
OF: of_irq_parse_one: dev=/soc@0/picasso/watchdog, index=0
OF: parent=/soc@0/pci@878000000000/gpio0@17,0, intsize=2
OF: intspec=4
OF: of_irq_parse_raw: ipar=/soc@0/pci@878000000000/gpio0@17,0, size=2
OF: -> addrsize=3
==================================================================
BUG: KASAN: slab-out-of-bounds in of_irq_parse_raw+0x2b8/0x8d0
Read of size 4 at addr ffffff81beca5608 by task bash/764
CPU: 1 PID: 764 Comm: bash Tainted: G O 6.1.67-484c613561-nokia_sm_arm64 #1
Hardware name: Unknown Unknown Product/Unknown Product, BIOS 2023.01-12.24.03-dirty 01/01/2023
Call trace:
dump_backtrace+0xdc/0x130
show_stack+0x1c/0x30
dump_stack_lvl+0x6c/0x84
print_report+0x150/0x448
kasan_report+0x98/0x140
__asan_load4+0x78/0xa0
of_irq_parse_raw+0x2b8/0x8d0
of_irq_parse_one+0x24c/0x270
parse_interrupts+0xc0/0x120
of_fwnode_add_links+0x100/0x2d0
fw_devlink_parse_fwtree+0x64/0xc0
device_add+0xb38/0xc30
of_device_add+0x64/0x90
of_platform_device_create_pdata+0xd0/0x170
of_platform_bus_create+0x244/0x600
of_platform_notify+0x1b0/0x254
blocking_notifier_call_chain+0x9c/0xd0
__of_changeset_entry_notify+0x1b8/0x230
__of_changeset_apply_notify+0x54/0xe4
of_overlay_fdt_apply+0xc04/0xd94
...
The buggy address belongs to the object at ffffff81beca5600
which belongs to the cache kmalloc-128 of size 128
The buggy address is located 8 bytes inside of
128-byte region [ffffff81beca5600, ffffff81beca5680)
The buggy address belongs to the physical page:
page:00000000230d3d03 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x1beca4
head:00000000230d3d03 order:1 compound_mapcount:0 compound_pincount:0
flags: 0x8000000000010200(slab|head|zone=2)
raw: 8000000000010200 0000000000000000 dead000000000122 ffffff810000c300
raw: 0000000000000000 0000000000200020 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffffff81beca5500: 04 fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffffff81beca5580: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
>ffffff81beca5600: 00 fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
^
ffffff81beca5680: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffffff81beca5700: 00 00 00 00 00 00 fc fc fc fc fc fc fc fc fc fc
==================================================================
OF: -> got it !Prevent the out-of-bounds read by copying the device address into a buffer of sufficient size.
--- drivers/of/irq.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
drivers/of/irq.c +11 -4
@@ -288,7 +288,8 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_arstruct device_node *p;const __be32 *addr;u32 intsize; -int i, res; +int i, res, addr_len; +__be32 addr_buf[3 ] = {0 };pr_debug ("of_irq_parse_one: dev=%pOF, index=%d\n" , device, index);
@@ -297,13 +298,19 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_arreturn of_irq_parse_oldworld (device, index, out_irq);/* Get the reg property (if any) */ - addr =of_get_property (device,"reg" ,NULL ); + addr =of_get_property (device,"reg" , &addr_len); + +/* Prevent out-of-bounds read in case of longer interrupt parent address size */ +if (addr_len > (3 *sizeof (__be32))) + addr_len =3 *sizeof (__be32); +if (addr) +memcpy (addr_buf, addr, addr_len);/* Try the new-style interrupts-extended first */ res =of_parse_phandle_with_args (device,"interrupts-extended" ,"#interrupt-cells" , index, out_irq);if (!res) -return of_irq_parse_raw (addr, out_irq); +return of_irq_parse_raw (addr_buf, out_irq);/* Look for the interrupt parent. */ p =of_irq_find_parent (device);
@@ -333,7 +340,7 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar/* Check if there are any interrupt-map translations to process */ - res =of_irq_parse_raw (addr, out_irq); + res =of_irq_parse_raw (addr_buf, out_irq); out:of_node_put (p);return res;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 169/214 lib/generic-radix-tree.c: Fix rare race in __genradix_ptr_alloc()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kent Overstreet <[email protected]>
[ Upstream commit b2f11c6f3e1fc60742673b8675c95b78447f3dae ]
If we need to increase the tree depth, allocate a new node, and then race with another thread that increased the tree depth before us, we'll still have a preallocated node that might be used later.
If we then use that node for a new non-root node, it'll still have a pointer to the old root instead of being zeroed - fix this by zeroing it in the cmpxchg failure path.
--- lib/generic-radix-tree.c | 2 ++ 1 file changed, 2 insertions(+)
lib/generic-radix-tree.c +2 -0
@@ -131,6 +131,8 @@ void *__genradix_ptr_alloc(struct __genradix *radix, size_t offset,if ((v =cmpxchg_release (&radix->root, r, new_root)) == r) { v = new_root; new_node =NULL ; + }else { + new_node->children[0 ] =NULL ; } }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 170/214 MIPS: cevt-r4k: Dont call get_c0_compare_int if timer irq is installed
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiaxun Yang <[email protected]>
[ Upstream commit 50f2b98dc83de7809a5c5bf0ccf9af2e75c37c13 ]
This avoids warning:
[ 0.118053] BUG: sleeping function called from invalid context at kernel/locking/mutex.c:283
Caused by get_c0_compare_int on secondary CPU.
We also skipped saving IRQ number to struct clock_event_device *cd as it's never used by clockevent core, as per comments it's only meant for "non CPU local devices".
--- arch/mips/kernel/cevt-r4k.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-)
arch/mips/kernel/cevt-r4k.c +7 -8
@@ -303,13 +303,6 @@ int r4k_clockevent_init(void)if (!c0_compare_int_usable ())return -ENXIO ; -/* -* With vectored interrupts things are getting platform specific. -* get_c0_compare_int is a hook to allow a platform to return the -* interrupt number of its liking. -*/ - irq =get_c0_compare_int (); - cd = &per_cpu (mips_clockevent_device, cpu); cd->name ="MIPS" ;
@@ -320,7 +313,6 @@ int r4k_clockevent_init(void) min_delta =calculate_min_delta (); cd->rating =300 ; - cd->irq = irq; cd->cpumask =cpumask_of (cpu); cd->set_next_event = mips_next_event; cd->event_handler = mips_event_handler;
@@ -332,6 +324,13 @@ int r4k_clockevent_init(void) cp0_timer_irq_installed =1 ; +/* +* With vectored interrupts things are getting platform specific. +* get_c0_compare_int is a hook to allow a platform to return the +* interrupt number of its liking. +*/ + irq =get_c0_compare_int (); +if (request_irq (irq, c0_compare_interrupt, flags,"timer" , c0_compare_interrupt))pr_err ("Failed to request irq %d (timer)\n" , irq);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 171/214 ata: pata_macio: Use WARN instead of BUG
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Ellerman <[email protected]>
[ Upstream commit d4bc0a264fb482b019c84fbc7202dd3cab059087 ]
The overflow/underflow conditions in pata_macio_qc_prep() should never happen. But if they do there's no need to kill the system entirely, a WARN and failing the IO request should be sufficient and might allow the system to keep running.
--- drivers/ata/pata_macio.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/ata/pata_macio.c +5 -2
@@ -540,7 +540,8 @@ static enum ata_completion_errors pata_macio_qc_prep(struct ata_queued_cmd *qc)while (sg_len) {/* table overflow should never happen */ -BUG_ON (pi++ >=MAX_DCMDS ); +if (WARN_ON_ONCE (pi >=MAX_DCMDS )) +return AC_ERR_SYSTEM ; len = (sg_len <MAX_DBDMA_SEG ) ? sg_len :MAX_DBDMA_SEG ; table->command =cpu_to_le16 (write ?OUTPUT_MORE :INPUT_MORE );
@@ -552,11 +553,13 @@ static enum ata_completion_errors pata_macio_qc_prep(struct ata_queued_cmd *qc) addr += len; sg_len -= len; ++table; + ++pi; } }/* Should never happen according to Tejun */ -BUG_ON (!pi); +if (WARN_ON_ONCE (!pi)) +return AC_ERR_SYSTEM ;/* Convert the last command to an input/output */ table--;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 172/214 NFSv4: Add missing rescheduling points in nfs_client_return_marked_delegations
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Trond Myklebust <[email protected]>
[ Upstream commit a017ad1313fc91bdf235097fd0a02f673fc7bb11 ]
We're seeing reports of soft lockups when iterating through the loops, so let's add rescheduling points.
--- fs/nfs/super.c | 2 ++ 1 file changed, 2 insertions(+)
fs/nfs/super.c +2 -0
@@ -47,6 +47,7 @@#include <linux/vfs.h> #include <linux/inet.h> #include <linux/in6.h> +#include <linux/sched.h> #include <linux/slab.h> #include <net/ipv6.h> #include <linux/netdevice.h>
@@ -219,6 +220,7 @@ static int __nfs_list_for_each_server(struct list_head *head, ret =fn (server, data);if (ret) goto out; +cond_resched ();rcu_read_lock (); }rcu_read_unlock ();
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 173/214 cifs: Check the lease context if we actually got a lease
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ronnie Sahlberg <[email protected]>
commit 66d45ca1350a3bb8d5f4db8879ccad3ed492337a upstream.
Some servers may return that we got a lease in rsp->OplockLevel but then in the lease context contradict this and say we got no lease at all. Thus we need to check the context if we have a lease. Additionally, If we do not get a lease we need to make sure we close the handle before we return an error to the caller.
--- fs/cifs/smb2ops.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-)
fs/cifs/smb2ops.c +16 -8
@@ -886,8 +886,6 @@ int open_cached_dir(unsigned int xid, st goto oshr_exit; } -atomic_inc (&tcon->num_remote_opens); - o_rsp = (struct smb2_create_rsp *)rsp_iov[0 ].iov_base; oparms.fid->persistent_fid = o_rsp->PersistentFileId; oparms.fid->volatile_fid = o_rsp->VolatileFileId;
@@ -897,8 +895,6 @@ int open_cached_dir(unsigned int xid, st tcon->crfid.tcon = tcon; tcon->crfid.is_valid = true; - tcon->crfid.dentry = dentry; -dget (dentry);kref_init (&tcon->crfid.refcount);/* BB TBD check to see if oplock level check can be removed below */
@@ -907,14 +903,16 @@ int open_cached_dir(unsigned int xid, st* See commit 2f94a3125b87. Increment the refcount when we * get a lease for root, release it if lease break occurs */ -kref_get (&tcon->crfid.refcount); - tcon->crfid.has_lease = true; rc =smb2_parse_contexts (server, rsp_iov, &oparms.fid->epoch, oparms.fid->lease_key, &oplock,NULL ,NULL );if (rc) goto oshr_exit; + +if (!(oplock &SMB2_LEASE_READ_CACHING_HE )) + goto oshr_exit; + }else goto oshr_exit;
@@ -928,7 +926,10 @@ int open_cached_dir(unsigned int xid, st (char *)&tcon->crfid.file_all_info)) tcon->crfid.file_all_info_is_valid = true; tcon->crfid.time = jiffies; - + tcon->crfid.dentry = dentry; +dget (dentry); +kref_get (&tcon->crfid.refcount); + tcon->crfid.has_lease = true; oshr_exit:mutex_unlock (&tcon->crfid.fid_mutex);
@@ -937,8 +938,15 @@ oshr_free:SMB2_query_info_free (&rqst[1 ]);free_rsp_buf (resp_buftype[0 ], rsp_iov[0 ].iov_base);free_rsp_buf (resp_buftype[1 ], rsp_iov[1 ].iov_base); -if (rc ==0 ) +if (rc) { +if (tcon->crfid.is_valid) +SMB2_close (0 , tcon, oparms.fid->persistent_fid, + oparms.fid->volatile_fid); + } +if (rc ==0 ) { *cfid = &tcon->crfid; +atomic_inc (&tcon->num_remote_opens); + }return rc; }
Greg Kroah-Hartman
maintainerPATCH 174/214 staging: iio: frequency: ad9834: Validate frequency parameter value
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aleksandr Mishin <[email protected]>
commit b48aa991758999d4e8f9296c5bbe388f293ef465 upstream.
In ad9834_write_frequency() clk_get_rate() can return 0. In such case ad9834_calc_freqreg() call will lead to division by zero. Checking 'if (fout > (clk_freq / 2))' doesn't protect in case of 'fout' is 0. ad9834_write_frequency() is called from ad9834_write(), where fout is taken from text buffer, which can contain any value.
Modify parameters checking.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- drivers/staging/iio/frequency/ad9834.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/staging/iio/frequency/ad9834.c +1 -1
@@ -114,7 +114,7 @@ static int ad9834_write_frequency(struct clk_freq =clk_get_rate (st->mclk); -if (fout > (clk_freq /2 )) +if (!clk_freq || fout > (clk_freq /2 ))return -EINVAL ; regval =ad9834_calc_freqreg (clk_freq, fout);
Greg Kroah-Hartman
maintainerPATCH 175/214 iio: buffer-dmaengine: fix releasing dma channel on error
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Lechner <[email protected]>
commit 84c65d8008764a8fb4e627ff02de01ec4245f2c4 upstream.
If dma_get_slave_caps() fails, we need to release the dma channel before returning an error to avoid leaking the channel.
--- drivers/iio/buffer/industrialio-buffer-dmaengine.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/iio/buffer/industrialio-buffer-dmaengine.c +3 -1
@@ -180,7 +180,7 @@ static struct iio_buffer *iio_dmaengine_ ret =dma_get_slave_caps (chan, &caps);if (ret <0 ) - goto err_free; + goto err_release;/* Needs to be aligned to the maximum of the minimums */ if (caps.src_addr_widths)
@@ -206,6 +206,8 @@ static struct iio_buffer *iio_dmaengine_return &dmaengine_buffer->queue.buffer; +err_release: +dma_release_channel (chan); err_free:kfree (dmaengine_buffer);return ERR_PTR (ret);
Greg Kroah-Hartman
maintainerPATCH 176/214 iio: fix scale application in iio_convert_raw_to_processed_unlocked
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matteo Martelli <[email protected]>
commit 8a3dcc970dc57b358c8db2702447bf0af4e0d83a upstream.
When the scale_type is IIO_VAL_INT_PLUS_MICRO or IIO_VAL_INT_PLUS_NANO the scale passed as argument is only applied to the fractional part of the value. Fix it by also multiplying the integer part by the scale provided.
--- drivers/iio/inkern.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/iio/inkern.c +4 -4
@@ -629,17 +629,17 @@ static int iio_convert_raw_to_processed_break ;case IIO_VAL_INT_PLUS_MICRO :if (scale_val2 <0 ) - *processed = -raw64 * scale_val; + *processed = -raw64 * scale_val * scale;else - *processed = raw64 * scale_val; + *processed = raw64 * scale_val * scale; *processed +=div_s64 (raw64 * (s64 )scale_val2 * scale,1000000LL );break ;case IIO_VAL_INT_PLUS_NANO :if (scale_val2 <0 ) - *processed = -raw64 * scale_val; + *processed = -raw64 * scale_val * scale;else - *processed = raw64 * scale_val; + *processed = raw64 * scale_val * scale; *processed +=div_s64 (raw64 * (s64 )scale_val2 * scale,1000000000LL );break ;
Greg Kroah-Hartman
maintainerPATCH 177/214 iio: adc: ad7124: fix config comparison
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dumitru Ceclan <[email protected]>
commit 2f6b92d0f69f04d9e2ea0db1228ab7f82f3173af upstream.
The ad7124_find_similar_live_cfg() computes the compare size by substracting the address of the cfg struct from the address of the live field. Because the live field is the first field in the struct, the result is 0.
Also, the memcmp() call is made from the start of the cfg struct, which includes the live and cfg_slot fields, which are not relevant for the comparison.
Fix by grouping the relevant fields with struct_group() and use the size of the group to compute the compare size; make the memcmp() call from the address of the group.
--- drivers/iio/adc/ad7124.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-)
drivers/iio/adc/ad7124.c +15 -11
@@ -144,15 +144,18 @@ struct ad7124_chip_info {struct ad7124_channel_config {bool live;unsigned int cfg_slot; -enum ad7124_ref_sel refsel; -bool bipolar; -bool buf_positive; -bool buf_negative; -unsigned int vref_mv; -unsigned int pga_bits; -unsigned int odr; -unsigned int odr_sel_bits; -unsigned int filter_type; +/* Following fields are used to compare equality. */ + struct_group(config_props, + enum ad7124_ref_sel refsel; +bool bipolar; +bool buf_positive; +bool buf_negative; +unsigned int vref_mv; +unsigned int pga_bits; +unsigned int odr; +unsigned int odr_sel_bits; +unsigned int filter_type; + ); };struct ad7124_channel {
@@ -331,11 +334,12 @@ static struct ad7124_channel_config *ad7ptrdiff_t cmp_size;int i; - cmp_size = (u8 *)&cfg->live - (u8 *)cfg; + cmp_size = sizeof_field(struct ad7124_channel_config, config_props);for (i =0 ; i < st->num_channels; i++) { cfg_aux = &st->channels[i].cfg; -if (cfg_aux->live && !memcmp (cfg, cfg_aux, cmp_size)) +if (cfg_aux->live && + !memcmp (&cfg->config_props, &cfg_aux->config_props, cmp_size))return cfg_aux; }
Greg Kroah-Hartman
maintainerPATCH 178/214 iio: adc: ad7606: remove frstdata check for serial mode
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guillaume Stols <[email protected]>
commit 90826e08468ba7fb35d8b39645b22d9e80004afe upstream.
The current implementation attempts to recover from an eventual glitch in the clock by checking frstdata state after reading the first channel's sample: If frstdata is low, it will reset the chip and return -EIO.
This will only work in parallel mode, where frstdata pin is set low after the 2nd sample read starts.
For the serial mode, according to the datasheet, "The FRSTDATA output returns to a logic low following the 16th SCLK falling edge.", thus after the Xth pulse, X being the number of bits in a sample, the check will always be true, and the driver will not work at all in serial mode if frstdata(optional) is defined in the devicetree as it will reset the chip, and return -EIO every time read_sample is called.
Hence, this check must be removed for serial mode.
--- drivers/iio/adc/ad7606.c | 28 +------------------------ drivers/iio/adc/ad7606.h | 2 + drivers/iio/adc/ad7606_par.c | 48 ++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 49 insertions(+), 29 deletions(-)
drivers/iio/adc/ad7606.c +2 -26
@@ -48,7 +48,7 @@ static const unsigned int ad7616_oversam 1, 2, 4, 8, 16, 32, 64, 128, }; -static int ad7606_reset (struct ad7606_state *st) +int ad7606_reset (struct ad7606_state *st) {if (st->gpio_reset) {gpiod_set_value (st->gpio_reset,1 );
@@ -59,6 +59,7 @@ static int ad7606_reset(struct ad7606_streturn -ENODEV ; } +EXPORT_SYMBOL_NS_GPL (ad7606_reset,IIO_AD7606 ); static int ad7606_reg_access(struct iio_dev *indio_dev, unsigned int reg,
@@ -87,31 +88,6 @@ static int ad7606_read_samples(struct ad {unsigned int num = st->chip_info->num_channels -1 ;u16 *data = st->data; -int ret; - -/* -* The frstdata signal is set to high while and after reading the sample -* of the first channel and low for all other channels. This can be used -* to check that the incoming data is correctly aligned. During normal -* operation the data should never become unaligned, but some glitch or -* electrostatic discharge might cause an extra read or clock cycle. -* Monitoring the frstdata signal allows to recover from such failure -* situations. -*/ - -if (st->gpio_frstdata) { - ret = st->bops->read_block (st->dev,1 , data); -if (ret) -return ret; - -if (!gpiod_get_value (st->gpio_frstdata)) { -ad7606_reset (st); -return -EIO ; - } - - data++; - num--; - }return st->bops->read_block (st->dev, num, data); }
drivers/iio/adc/ad7606.h +2 -0
@@ -153,6 +153,8 @@ int ad7606_probe(struct device *dev, int const char *name, unsigned int id, const struct ad7606_bus_ops *bops); +int ad7606_reset (struct ad7606_state *st); +enum ad7606_supported_device_ids {ID_AD7605_4 ,ID_AD7606_8 ,
drivers/iio/adc/ad7606_par.c +45 -3
67 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 179/214 iio: adc: ad7124: fix chip ID mismatch
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dumitru Ceclan <[email protected]>
commit 96f9ab0d5933c1c00142dd052f259fce0bc3ced2 upstream.
The ad7124_soft_reset() function has the assumption that the chip will assert the "power-on reset" bit in the STATUS register after a software reset without any delay. The POR bit =0 is used to check if the chip initialization is done.
A chip ID mismatch probe error appears intermittently when the probe continues too soon and the ID register does not contain the expected value.
Fix by adding a 200us delay after the software reset command is issued.
--- drivers/iio/adc/ad7124.c | 1 + 1 file changed, 1 insertion(+)
drivers/iio/adc/ad7124.c +1 -0
@@ -690,6 +690,7 @@ static int ad7124_soft_reset(struct ad71if (ret <0 )return ret; +fsleep (200 ); timeout =100 ; do { ret = ad_sd_read_reg(&st->sd, AD7124_STATUS, 1, &readval);
Greg Kroah-Hartman
maintainerPATCH 180/214 usb: dwc3: core: update LC timer as per USB Spec V3.2
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Faisal Hassan <[email protected]>
commit 9149c9b0c7e046273141e41eebd8a517416144ac upstream.
This fix addresses STAR 9001285599, which only affects DWC_usb3 version 3.20a. The timer value for PM_LC_TIMER in DWC_usb3 3.20a for the Link ECN changes is incorrect. If the PM TIMER ECN is enabled via GUCTL2[19], the link compliance test (TD7.21) may fail. If the ECN is not enabled (GUCTL2[19] = 0), the controller will use the old timer value (5us), which is still acceptable for the link compliance test. Therefore, clear GUCTL2[19] to pass the USB link compliance test: TD 7.21.
--- drivers/usb/dwc3/core.c | 15 +++++++++++++++ drivers/usb/dwc3/core.h | 2 ++ 2 files changed, 17 insertions(+)
drivers/usb/dwc3/core.c +15 -0
@@ -1058,6 +1058,21 @@ static int dwc3_core_init(struct dwc3 *d }/* +* STAR 9001285599: This issue affects DWC_usb3 version 3.20a +* only. If the PM TIMER ECM is enabled through GUCTL2[19], the +* link compliance test (TD7.21) may fail. If the ECN is not +* enabled (GUCTL2[19] = 0), the controller will use the old timer +* value (5us), which is still acceptable for the link compliance +* test. Therefore, do not enable PM TIMER ECM in 3.20a by +* setting GUCTL2[19] by default; instead, use GUCTL2[19] = 0. +*/ + if (DWC3_VER_IS(DWC3, 320A)) { + reg =dwc3_readl (dwc->regs,DWC3_GUCTL2 ); + reg &= ~DWC3_GUCTL2_LC_TIMER ; +dwc3_writel (dwc->regs,DWC3_GUCTL2 , reg); + } + +/* * When configured in HOST mode, after issuing U3/L2 exit controller * fails to send proper CRC checksum in CRC5 feild. Because of this * behaviour Transaction Error is generated, resulting in reset and
drivers/usb/dwc3/core.h +2 -0
@@ -387,6 +387,7 @@/* Global User Control Register 2 */ #define DWC3_GUCTL2_RST_ACTBITLATER BIT(14) +#define DWC3_GUCTL2_LC_TIMER BIT(19)/* Global User Control Register 3 */ #define DWC3_GUCTL3_SPLITDISABLE BIT(14)
@@ -1197,6 +1198,7 @@ struct dwc3 {#define DWC3_REVISION_290A 0x5533290a#define DWC3_REVISION_300A 0x5533300a#define DWC3_REVISION_310A 0x5533310a +#define DWC3_REVISION_320A 0x5533320a#define DWC3_REVISION_330A 0x5533330a#define DWC31_REVISION_ANY 0x0
Greg Kroah-Hartman
maintainerPATCH 181/214 binder: fix UAF caused by offsets overwrite
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Carlos Llamas <[email protected]>
commit 4df153652cc46545722879415937582028c18af5 upstream.
Binder objects are processed and copied individually into the target buffer during transactions. Any raw data in-between these objects is copied as well. However, this raw data copy lacks an out-of-bounds check. If the raw data exceeds the data section size then the copy overwrites the offsets section. This eventually triggers an error that attempts to unwind the processed objects. However, at this point the offsets used to index these objects are now corrupted.
Unwinding with corrupted offsets can result in decrements of arbitrary nodes and lead to their premature release. Other users of such nodes are left with a dangling pointer triggering a use-after-free. This issue is made evident by the following KASAN report (trimmed):
==================================================================
BUG: KASAN: slab-use-after-free in _raw_spin_lock+0xe4/0x19c Write of size 4 at addr ffff47fc91598f04 by task binder-util/743 CPU: 9 UID: 0 PID: 743 Comm: binder-util Not tainted 6.11.0-rc4 #1 Hardware name: linux,dummy-virt (DT) Call trace: _raw_spin_lock+0xe4/0x19c binder_free_buf+0x128/0x434 binder_thread_write+0x8a4/0x3260 binder_ioctl+0x18f0/0x258c [...] Allocated by task 743: __kmalloc_cache_noprof+0x110/0x270 binder_new_node+0x50/0x700 binder_transaction+0x413c/0x6da8 binder_thread_write+0x978/0x3260 binder_ioctl+0x18f0/0x258c [...] Freed by task 745: kfree+0xbc/0x208 binder_thread_read+0x1c5c/0x37d4 binder_ioctl+0x16d8/0x258c [...] ==================================================================
To avoid this issue, let's check that the raw data copy is within the boundaries of the data section.
--- drivers/android/binder.c | 1 + 1 file changed, 1 insertion(+)
drivers/android/binder.c +1 -0
@@ -3173,6 +3173,7 @@ static void binder_transaction(struct bi*/ copy_size = object_offset - user_offset; if (copy_size && (user_offset > object_offset || + object_offset > tr->data_size || binder_alloc_copy_user_to_buffer( &target_proc->alloc, t->buffer, user_offset,
Greg Kroah-Hartman
maintainerPATCH 182/214 nvmem: Fix return type of devm_nvmem_device_get() in kerneldoc
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Geert Uytterhoeven <[email protected]>
commit c69f37f6559a8948d70badd2b179db7714dedd62 upstream.
devm_nvmem_device_get() returns an nvmem device, not an nvmem cell.
--- drivers/nvmem/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/nvmem/core.c +3 -3
@@ -1112,13 +1112,13 @@ void nvmem_device_put(struct nvmem_devicEXPORT_SYMBOL_GPL (nvmem_device_put);/** -* devm_nvmem_device_get() - Get nvmem cell of device form a given id +* devm_nvmem_device_get() - Get nvmem device of device form a given id * * @dev: Device that requests the nvmem device. * @id: name id for the requested nvmem device. * -* Return: ERR_PTR() on error or a valid pointer to a struct nvmem_cell -* on success. The nvmem_cell will be freed by the automatically once the +* Return: ERR_PTR() on error or a valid pointer to a struct nvmem_device +* on success. The nvmem_device will be freed by the automatically once the * device is freed. */ struct nvmem_device *devm_nvmem_device_get (struct device *dev,const char *id)
Greg Kroah-Hartman
maintainerPATCH 183/214 uio_hv_generic: Fix kernel NULL pointer dereference in hv_uio_rescind
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Saurabh Sengar <[email protected]>
commit fb1adbd7e50f3d2de56d0a2bb0700e2e819a329e upstream.
For primary VM Bus channels, primary_channel pointer is always NULL. This pointer is valid only for the secondary channels. Also, rescind callback is meant for primary channels only.
Fix NULL pointer dereference by retrieving the device_obj from the parent for the primary channel.
--- drivers/uio/uio_hv_generic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/uio/uio_hv_generic.c +2 -1
@@ -104,10 +104,11 @@ static void hv_uio_channel_cb(void *cont/* * Callback from vmbus_event when channel is rescinded. +* It is meant for rescind of primary channels only. */ static void hv_uio_rescind (struct vmbus_channel *channel) { -struct hv_device *hv_dev = channel->primary_channel->device_obj; +struct hv_device *hv_dev = channel->device_obj;struct hv_uio_private_data *pdata =hv_get_drvdata (hv_dev);/*
Greg Kroah-Hartman
maintainerPATCH 184/214 Drivers: hv: vmbus: Fix rescind handling in uio_hv_generic
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Naman Jain <[email protected]>
commit 6fd28941447bf2c8ca0f26fda612a1cabc41663f upstream.
Rescind offer handling relies on rescind callbacks for some of the resources cleanup, if they are registered. It does not unregister vmbus device for the primary channel closure, when callback is registered. Without it, next onoffer does not come, rescind flag remains set and device goes to unusable state.
Add logic to unregister vmbus for the primary channel in rescind callback to ensure channel removal and relid release, and to ensure that next onoffer can be received and handled properly.
--- drivers/hv/vmbus_drv.c | 1 + drivers/uio/uio_hv_generic.c | 8 ++++++++ 2 files changed, 9 insertions(+)
drivers/hv/vmbus_drv.c +1 -0
@@ -2008,6 +2008,7 @@ static umode_t vmbus_chan_attr_is_visiblreturn attr->mode; } +EXPORT_SYMBOL_GPL (vmbus_device_unregister);static struct attribute_group vmbus_chan_group = { .attrs = vmbus_chan_attrs,
drivers/uio/uio_hv_generic.c +8 -0
@@ -119,6 +119,14 @@ static void hv_uio_rescind(struct vmbus_/* Wake up reader */ uio_event_notify (&pdata->info); + +/* +* With rescind callback registered, rescind path will not unregister the device +* from vmbus when the primary channel is rescinded. +* Without it, rescind handling is incomplete and next onoffer msg does not come. +* Unregister the device from vmbus here. +*/ +vmbus_device_unregister (channel->device_obj); }/* Sysfs API to allow mmap of the ring buffers
Greg Kroah-Hartman
maintainerPATCH 185/214 VMCI: Fix use-after-free when removing resource in vmci_resource_remove()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Fernandez Gonzalez <[email protected]>
commit 48b9a8dabcc3cf5f961b2ebcd8933bf9204babb7 upstream.
When removing a resource from vmci_resource_table in vmci_resource_remove(), the search is performed using the resource handle by comparing context and resource fields.
It is possible though to create two resources with different types but same handle (same context and resource fields).
When trying to remove one of the resources, vmci_resource_remove() may not remove the intended one, but the object will still be freed as in the case of the datagram type in vmci_datagram_destroy_handle(). vmci_resource_table will still hold a pointer to this freed resource leading to a use-after-free vulnerability.
BUG: KASAN: use-after-free in vmci_handle_is_equal include/linux/vmw_vmci_defs.h:142 [inline] BUG: KASAN: use-after-free in vmci_resource_remove+0x3a1/0x410 drivers/misc/vmw_vmci/vmci_resource.c:147 Read of size 4 at addr ffff88801c16d800 by task syz-executor197/1592 Call Trace: <TASK> __dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0x82/0xa9 lib/dump_stack.c:106 print_address_description.constprop.0+0x21/0x366 mm/kasan/report.c:239 __kasan_report.cold+0x7f/0x132 mm/kasan/report.c:425 kasan_report+0x38/0x51 mm/kasan/report.c:442 vmci_handle_is_equal include/linux/vmw_vmci_defs.h:142 [inline] vmci_resource_remove+0x3a1/0x410 drivers/misc/vmw_vmci/vmci_resource.c:147 vmci_qp_broker_detach+0x89a/0x11b9 drivers/misc/vmw_vmci/vmci_queue_pair.c:2182 ctx_free_ctx+0x473/0xbe1 drivers/misc/vmw_vmci/vmci_context.c:444 kref_put include/linux/kref.h:65 [inline] vmci_ctx_put drivers/misc/vmw_vmci/vmci_context.c:497 [inline] vmci_ctx_destroy+0x170/0x1d6 drivers/misc/vmw_vmci/vmci_context.c:195 vmci_host_close+0x125/0x1ac drivers/misc/vmw_vmci/vmci_host.c:143 __fput+0x261/0xa34 fs/file_table.c:282 task_work_run+0xf0/0x194 kernel/task_work.c:164 tracehook_notify_resume include/linux/tracehook.h:189 [inline] exit_to_user_mode_loop+0x184/0x189 kernel/entry/common.c:187 exit_to_user_mode_prepare+0x11b/0x123 kernel/entry/common.c:220 __syscall_exit_to_user_mode_work kernel/entry/common.c:302 [inline] syscall_exit_to_user_mode+0x18/0x42 kernel/entry/common.c:313 do_syscall_64+0x41/0x85 arch/x86/entry/common.c:86 entry_SYSCALL_64_after_hwframe+0x6e/0x0
This change ensures the type is also checked when removing the resource from vmci_resource_table in vmci_resource_remove().
--- drivers/misc/vmw_vmci/vmci_resource.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/misc/vmw_vmci/vmci_resource.c +2 -1
@@ -144,7 +144,8 @@ void vmci_resource_remove(struct vmci_respin_lock (&vmci_resource_table.lock);hlist_for_each_entry (r, &vmci_resource_table.entries[idx], node) { -if (vmci_handle_is_equal (r->handle, resource->handle)) { +if (vmci_handle_is_equal (r->handle, resource->handle) && + resource->type == r->type) {hlist_del_init_rcu (&r->node);break ; }
Greg Kroah-Hartman
maintainerPATCH 186/214 clocksource/drivers/imx-tpm: Fix return -ETIME when delta exceeds INT_MAX
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jacky Bai <[email protected]>
commit 5b8843fcd49827813da80c0f590a17ae4ce93c5d upstream.
In tpm_set_next_event(delta), return -ETIME by wrong cast to int when delta is larger than INT_MAX.
For example:
tpm_set_next_event(delta = 0xffff_fffe)
{
...
next = tpm_read_counter(); // assume next is 0x10
next += delta; // next will 0xffff_fffe + 0x10 = 0x1_0000_000e
now = tpm_read_counter(); // now is 0x10
...
return (int)(next - now) <= 0 ? -ETIME : 0;
^^^^^^^^^^
0x1_0000_000e - 0x10 = 0xffff_fffe, which is -2 when
cast to int. So return -ETIME.
}To fix this, introduce a 'prev' variable and check if 'now - prev' is larger than delta.
--- drivers/clocksource/timer-imx-tpm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/clocksource/timer-imx-tpm.c +4 -4
@@ -83,10 +83,10 @@ static u64 notrace tpm_read_sched_clock(static int tpm_set_next_event (unsigned long delta,struct clock_event_device *evt) { -unsigned long next, now; +unsigned long next, prev, now; - next =tpm_read_counter (); - next += delta; + prev =tpm_read_counter (); + next = prev + delta;writel (next, timer_base +TPM_C0V ); now =tpm_read_counter ();
@@ -96,7 +96,7 @@ static int tpm_set_next_event(unsigned l* of writing CNT registers which may cause the min_delta event got * missed, so we need add a ETIME check here in case it happened. */ -return (int )(next - now) <=0 ? -ETIME :0 ; +return (now - prev) >= delta ? -ETIME :0 ; }static int tpm_set_state_oneshot (struct clock_event_device *evt)
Greg Kroah-Hartman
maintainerPATCH 187/214 clocksource/drivers/imx-tpm: Fix next event not taking effect sometime
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jacky Bai <[email protected]>
commit 3d5c2f8e75a55cfb11a85086c71996af0354a1fb upstream.
The value written into the TPM CnV can only be updated into the hardware when the counter increases. Additional writes to the CnV write buffer are ignored until the register has been updated. Therefore, we need to check if the CnV has been updated before continuing. This may require waiting for 1 counter cycle in the worst case.
--- drivers/clocksource/timer-imx-tpm.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/clocksource/timer-imx-tpm.c +8 -0
@@ -91,6 +91,14 @@ static int tpm_set_next_event(unsigned l now =tpm_read_counter ();/* +* Need to wait CNT increase at least 1 cycle to make sure +* the C0V has been updated into HW. +*/ +if ((next &0xffffffff ) !=readl (timer_base +TPM_C0V )) +while (now ==tpm_read_counter ()) + ; + +/* * NOTE: We observed in a very small probability, the bus fabric * contention between GPU and A7 may results a few cycles delay * of writing CNT registers which may cause the min_delta event got
Greg Kroah-Hartman
maintainerPATCH 188/214 clocksource/drivers/timer-of: Remove percpu irq related code
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Lezcano <[email protected]>
commit 471ef0b5a8aaca4296108e756b970acfc499ede4 upstream.
GCC's named address space checks errors out with:
drivers/clocksource/timer-of.c: In function ‘timer_of_irq_exit’:drivers/clocksource/timer-of.c:29:46: error: passing argument 2 of ‘free_percpu_irq’ from pointer to non-enclosed address space
29 | free_percpu_irq(of_irq->irq, clkevt);
| ^~~~~~
In file included from drivers/clocksource/timer-of.c:8:./include/linux/interrupt.h:201:43: note: expected ‘__seg_gs void *’ but argument is of type ‘struct clock_event_device *’
201 | extern void free_percpu_irq(unsigned int, void __percpu *);
| ^~~~~~~~~~~~~~~drivers/clocksource/timer-of.c: In function ‘timer_of_irq_init’:drivers/clocksource/timer-of.c:74:51: error: passing argument 4 of ‘request_percpu_irq’ from pointer to non-enclosed address space
74 | np->full_name, clkevt) :
| ^~~~~~./include/linux/interrupt.h:190:56: note: expected ‘__seg_gs void *’ but argument is of type ‘struct clock_event_device *’
190 | const char *devname, void __percpu *percpu_dev_id)
Sparse warns about:
timer-of.c:29:46: warning: incorrect type in argument 2 (different address spaces)
timer-of.c:29:46: expected void [noderef] __percpu *
timer-of.c:29:46: got struct clock_event_device *clkevt
timer-of.c:74:51: warning: incorrect type in argument 4 (different address spaces)
timer-of.c:74:51: expected void [noderef] __percpu *percpu_dev_id
timer-of.c:74:51: got struct clock_event_device *clkevt
It appears the code is incorrect as reported by Uros Bizjak:
"The referred code is questionable as it tries to reuse the clkevent pointer once as percpu pointer and once as generic pointer, which should be avoided."
This change removes the percpu related code as no drivers is using it.
[Daniel: Fixed the description]
--- drivers/clocksource/timer-of.c | 17 ++++------------- drivers/clocksource/timer-of.h | 1 - 2 files changed, 4 insertions(+), 14 deletions(-)
drivers/clocksource/timer-of.c +4 -13
@@ -25,10 +25,7 @@ static __init void timer_of_irq_exit(strstruct clock_event_device *clkevt = &to->clkevt; -if (of_irq->percpu) -free_percpu_irq (of_irq->irq, clkevt); -else -free_irq (of_irq->irq, clkevt); +free_irq (of_irq->irq, clkevt); }/**
@@ -42,9 +39,6 @@ static __init void timer_of_irq_exit(str* - Get interrupt number by name * - Get interrupt number by index * -* When the interrupt is per CPU, 'request_percpu_irq()' is called, -* otherwise 'request_irq()' is used. -* * Returns 0 on success, < 0 otherwise */ static __init int timer_of_irq_init(struct device_node *np,
@@ -69,12 +63,9 @@ static __init int timer_of_irq_init(strureturn -EINVAL ; } - ret = of_irq->percpu ? -request_percpu_irq (of_irq->irq, of_irq->handler, - np->full_name, clkevt) : -request_irq (of_irq->irq, of_irq->handler, - of_irq->flags ? of_irq->flags :IRQF_TIMER , - np->full_name, clkevt); + ret =request_irq (of_irq->irq, of_irq->handler, + of_irq->flags ? of_irq->flags :IRQF_TIMER , + np->full_name, clkevt);if (ret) {pr_err ("Failed to request irq %d for %pOF\n" , of_irq->irq, np);return ret;
drivers/clocksource/timer-of.h +0 -1
@@ -11,7 +11,6 @@struct of_timer_irq {int irq;int index; -int percpu;const char *name;unsigned long flags;irq_handler_t handler;
Greg Kroah-Hartman
maintainerPATCH 189/214 uprobes: Use kzalloc to allocate xol area
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Schnelle <[email protected]>
commit e240b0fde52f33670d1336697c22d90a4fe33c84 upstream.
To prevent unitialized members, use kzalloc to allocate the xol area.
--- kernel/events/uprobes.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
kernel/events/uprobes.c +1 -2
@@ -1484,7 +1484,7 @@ static struct xol_area *__create_xol_areuprobe_opcode_t insn =UPROBE_SWBP_INSN ;struct xol_area *area; - area =kmalloc (sizeof (*area),GFP_KERNEL ); + area =kzalloc (sizeof (*area),GFP_KERNEL );if (unlikely (!area)) goto out;
@@ -1494,7 +1494,6 @@ static struct xol_area *__create_xol_are goto free_area; area->xol_mapping.name ="[uprobes]" ; - area->xol_mapping.fault =NULL ; area->xol_mapping.pages = area->pages; area->pages[0 ] =alloc_page (GFP_HIGHUSER );if (!area->pages[0 ])
Greg Kroah-Hartman
maintainerPATCH 190/214 perf/aux: Fix AUX buffer serialization
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Zijlstra <[email protected]>
commit 2ab9d830262c132ab5db2f571003d80850d56b2a upstream.
Ole reported that event->mmap_mutex is strictly insufficient to serialize the AUX buffer, add a per RB mutex to fully serialize it.
Note that in the lock order comment the perf_event::mmap_mutex order was already wrong, that is, it nesting under mmap_lock is not new with this patch.
--- kernel/events/core.c | 18 ++++++++++++------ kernel/events/internal.h | 1 + kernel/events/ring_buffer.c | 2 ++ 3 files changed, 15 insertions(+), 6 deletions(-)
kernel/events/core.c +12 -6
@@ -1368,8 +1368,9 @@ static void put_ctx(struct perf_event_co* perf_event_context::mutex * perf_event::child_mutex; * perf_event_context::lock -* perf_event::mmap_mutex * mmap_lock +* perf_event::mmap_mutex +* perf_buffer::aux_mutex * perf_addr_filters_head::lock * * cpu_hotplug_lock
@@ -6275,12 +6276,11 @@ static void perf_mmap_close(struct vm_ar event->pmu->event_unmapped (event, vma->vm_mm);/* -* rb->aux_mmap_count will always drop before rb->mmap_count and -* event->mmap_count, so it is ok to use event->mmap_mutex to -* serialize with perf_mmap here. +* The AUX buffer is strictly a sub-buffer, serialize using aux_mutex +* to avoid complications. */ if (rb_has_aux (rb) && vma->vm_pgoff == rb->aux_pgoff && -atomic_dec_and_mutex_lock (&rb->aux_mmap_count, &event->mmap_mutex)) { +atomic_dec_and_mutex_lock (&rb->aux_mmap_count, &rb->aux_mutex)) {/* * Stop all AUX events that are writing to this buffer, * so that we can free its AUX pages and corresponding PMU
@@ -6297,7 +6297,7 @@ static void perf_mmap_close(struct vm_arrb_free_aux (rb);WARN_ON_ONCE (refcount_read (&rb->aux_refcount)); -mutex_unlock (&event->mmap_mutex); +mutex_unlock (&rb->aux_mutex); }if (atomic_dec_and_test (&rb->mmap_count))
@@ -6385,6 +6385,7 @@ static int perf_mmap(struct file *file,struct perf_event *event = file->private_data;unsigned long user_locked, user_lock_limit;struct user_struct *user =current_user (); +struct mutex *aux_mutex =NULL ;struct perf_buffer *rb =NULL ;unsigned long locked, lock_limit;unsigned long vma_size;
@@ -6433,6 +6434,9 @@ static int perf_mmap(struct file *file,if (!rb) goto aux_unlock; + aux_mutex = &rb->aux_mutex; +mutex_lock (aux_mutex); + aux_offset =READ_ONCE (rb->user_page->aux_offset); aux_size =READ_ONCE (rb->user_page->aux_size);
@@ -6583,6 +6587,8 @@ unlock:atomic_dec (&rb->mmap_count); } aux_unlock: +if (aux_mutex) +mutex_unlock (aux_mutex);mutex_unlock (&event->mmap_mutex);/*
kernel/events/internal.h +1 -0
@@ -40,6 +40,7 @@ struct perf_buffer {struct user_struct *mmap_user;/* AUX area */ +struct mutex aux_mutex;long aux_head;unsigned int aux_nest;long aux_wakeup;/* last aux_watermark boundary crossed by aux_head */
kernel/events/ring_buffer.c +2 -0
@@ -332,6 +332,8 @@ ring_buffer_init(struct perf_buffer *rb,*/ if (!rb->nr_pages) rb->paused =1 ; + +mutex_init (&rb->aux_mutex); }void perf_aux_output_flag (struct perf_output_handle *handle,u64 flags)
Greg Kroah-Hartman
maintainerPATCH 191/214 ksmbd: unset the binding mark of a reused connection
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namjae Jeon <[email protected]>
[ Upstream commit 78c5a6f1f630172b19af4912e755e1da93ef0ab5 ]
Steve French reported null pointer dereference error from sha256 lib. cifs.ko can send session setup requests on reused connection. If reused connection is used for binding session, conn->binding can still remain true and generate_preauth_hash() will not set sess->Preauth_HashValue and it will be NULL.
It is used as a material to create an encryption key in ksmbd_gen_smb311_encryptionkey. ->Preauth_HashValue cause null pointer dereference error from crypto_shash_update().
BUG: kernel NULL pointer dereference, address: 0000000000000000 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page PGD 0 P4D 0 Oops: 0000 [#1] PREEMPT SMP PTI CPU: 8 PID: 429254 Comm: kworker/8:39 Hardware name: LENOVO 20MAS08500/20MAS08500, BIOS N2CET69W (1.52 ) Workqueue: ksmbd-io handle_ksmbd_work [ksmbd] RIP: 0010:lib_sha256_base_do_update.isra.0+0x11e/0x1d0 [sha256_ssse3] <TASK> ? show_regs+0x6d/0x80 ? __die+0x24/0x80 ? page_fault_oops+0x99/0x1b0 ? do_user_addr_fault+0x2ee/0x6b0 ? exc_page_fault+0x83/0x1b0 ? asm_exc_page_fault+0x27/0x30 ? __pfx_sha256_transform_rorx+0x10/0x10 [sha256_ssse3] ? lib_sha256_base_do_update.isra.0+0x11e/0x1d0 [sha256_ssse3] ? __pfx_sha256_transform_rorx+0x10/0x10 [sha256_ssse3] ? __pfx_sha256_transform_rorx+0x10/0x10 [sha256_ssse3] _sha256_update+0x77/0xa0 [sha256_ssse3] sha256_avx2_update+0x15/0x30 [sha256_ssse3] crypto_shash_update+0x1e/0x40 hmac_update+0x12/0x20 crypto_shash_update+0x1e/0x40 generate_key+0x234/0x380 [ksmbd] generate_smb3encryptionkey+0x40/0x1c0 [ksmbd] ksmbd_gen_smb311_encryptionkey+0x72/0xa0 [ksmbd] ntlm_authenticate.isra.0+0x423/0x5d0 [ksmbd] smb2_sess_setup+0x952/0xaa0 [ksmbd] __process_request+0xa3/0x1d0 [ksmbd] __handle_ksmbd_work+0x1c4/0x2f0 [ksmbd] handle_ksmbd_work+0x2d/0xa0 [ksmbd] process_one_work+0x16c/0x350 worker_thread+0x306/0x440 ? __pfx_worker_thread+0x10/0x10 kthread+0xef/0x120 ? __pfx_kthread+0x10/0x10 ret_from_fork+0x44/0x70 ? __pfx_kthread+0x10/0x10 ret_from_fork_asm+0x1b/0x30 </TASK>
--- fs/ksmbd/smb2pdu.c | 4 ++++ 1 file changed, 4 insertions(+)
fs/ksmbd/smb2pdu.c +4 -0
@@ -1705,6 +1705,8 @@ int smb2_sess_setup(struct ksmbd_work *work) rc =ksmbd_session_register (conn, sess);if (rc) goto out_err; + + conn->binding = false; }else if (conn->dialect >=SMB30_PROT_ID && (server_conf.flags &KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL ) && req->Flags &SMB2_SESSION_REQ_FLAG_BINDING ) {
@@ -1783,6 +1785,8 @@ int smb2_sess_setup(struct ksmbd_work *work) sess =NULL ; goto out_err; } + + conn->binding = false; } work->sess = sess;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 192/214 ksmbd: Unlock on in ksmbd_tcp_set_interfaces()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
[ Upstream commit 844436e045ac2ab7895d8b281cb784a24de1d14d ]
Unlock before returning an error code if this allocation fails.
--- fs/ksmbd/transport_tcp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
fs/ksmbd/transport_tcp.c +3 -1
@@ -618,8 +618,10 @@ int ksmbd_tcp_set_interfaces(char *ifc_list, int ifc_list_sz)for_each_netdev (&init_net, netdev) {if (netif_is_bridge_port (netdev))continue ; -if (!alloc_iface (kstrdup (netdev->name,GFP_KERNEL ))) +if (!alloc_iface (kstrdup (netdev->name,GFP_KERNEL ))) { +rtnl_unlock ();return -ENOMEM ; + } }rtnl_unlock (); bind_additional_ifaces =1 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 193/214 nilfs2: replace snprintf in show functions with sysfs_emit
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qing Wang <[email protected]>
[ Upstream commit 3bcd6c5bd483287f4a09d3d59a012d47677b6edc ]
Patch series "nilfs2 updates".
This patch (of 2):
coccicheck complains about the use of snprintf() in sysfs show functions.
Fix the coccicheck warning:
WARNING: use scnprintf or sprintf.
Use sysfs_emit instead of scnprintf or sprintf makes more sense.
Stable-dep-of: 683408258917 ("nilfs2: protect references to superblock parameters exposed in sysfs")
--- fs/nilfs2/sysfs.c | 76 +++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 38 deletions(-)
fs/nilfs2/sysfs.c +38 -38
@@ -95,7 +95,7 @@ static ssize_t nilfs_snapshot_inodes_count_show(struct nilfs_snapshot_attr *attr, struct nilfs_root *root, char *buf) { - return snprintf(buf, PAGE_SIZE, "%llu\n", + return sysfs_emit(buf, "%llu\n", (unsigned long long)atomic64_read(&root->inodes_count)); }
@@ -103,7 +103,7 @@ static ssize_t nilfs_snapshot_blocks_count_show(struct nilfs_snapshot_attr *attr, struct nilfs_root *root, char *buf) { - return snprintf(buf, PAGE_SIZE, "%llu\n", + return sysfs_emit(buf, "%llu\n", (unsigned long long)atomic64_read(&root->blocks_count)); }
@@ -116,7 +116,7 @@ static ssize_t nilfs_snapshot_README_show(struct nilfs_snapshot_attr *attr, struct nilfs_root *root, char *buf) { - return snprintf(buf, PAGE_SIZE, snapshot_readme_str); + return sysfs_emit(buf, snapshot_readme_str); }NILFS_SNAPSHOT_RO_ATTR (inodes_count);
@@ -217,7 +217,7 @@ static ssize_t nilfs_mounted_snapshots_README_show(struct nilfs_mounted_snapshots_attr *attr, struct the_nilfs *nilfs, char *buf) { - return snprintf(buf, PAGE_SIZE, mounted_snapshots_readme_str); + return sysfs_emit(buf, mounted_snapshots_readme_str); }NILFS_MOUNTED_SNAPSHOTS_RO_ATTR (README );
@@ -255,7 +255,7 @@ nilfs_checkpoints_checkpoints_number_show(struct nilfs_checkpoints_attr *attr, ncheckpoints = cpstat.cs_ncps; -return snprintf (buf,PAGE_SIZE ,"%llu\n" , ncheckpoints); +return sysfs_emit (buf,"%llu\n" , ncheckpoints); } static ssize_t
@@ -278,7 +278,7 @@ nilfs_checkpoints_snapshots_number_show(struct nilfs_checkpoints_attr *attr, nsnapshots = cpstat.cs_nsss; -return snprintf (buf,PAGE_SIZE ,"%llu\n" , nsnapshots); +return sysfs_emit (buf,"%llu\n" , nsnapshots); } static ssize_t
@@ -292,7 +292,7 @@ nilfs_checkpoints_last_seg_checkpoint_show(struct nilfs_checkpoints_attr *attr, last_cno = nilfs->ns_last_cno;spin_unlock (&nilfs->ns_last_segment_lock); -return snprintf (buf,PAGE_SIZE ,"%llu\n" , last_cno); +return sysfs_emit (buf,"%llu\n" , last_cno); } static ssize_t
@@ -306,7 +306,7 @@ nilfs_checkpoints_next_checkpoint_show(struct nilfs_checkpoints_attr *attr, cno = nilfs->ns_cno;up_read (&nilfs->ns_segctor_sem); -return snprintf (buf,PAGE_SIZE ,"%llu\n" , cno); +return sysfs_emit (buf,"%llu\n" , cno); } static const char checkpoints_readme_str[] =
@@ -322,7 +322,7 @@ static ssize_t nilfs_checkpoints_README_show(struct nilfs_checkpoints_attr *attr, struct the_nilfs *nilfs, char *buf) { - return snprintf(buf, PAGE_SIZE, checkpoints_readme_str); + return sysfs_emit(buf, checkpoints_readme_str); }NILFS_CHECKPOINTS_RO_ATTR (checkpoints_number);
@@ -353,7 +353,7 @@ nilfs_segments_segments_number_show(struct nilfs_segments_attr *attr,struct the_nilfs *nilfs, char *buf) { - return snprintf(buf, PAGE_SIZE, "%lu\n", nilfs->ns_nsegments); + return sysfs_emit(buf, "%lu\n", nilfs->ns_nsegments); } static ssize_t
@@ -361,7 +361,7 @@ nilfs_segments_blocks_per_segment_show(struct nilfs_segments_attr *attr,struct the_nilfs *nilfs, char *buf) { - return snprintf(buf, PAGE_SIZE, "%lu\n", nilfs->ns_blocks_per_segment); + return sysfs_emit(buf, "%lu\n", nilfs->ns_blocks_per_segment); } static ssize_t
@@ -375,7 +375,7 @@ nilfs_segments_clean_segments_show(struct nilfs_segments_attr *attr, ncleansegs =nilfs_sufile_get_ncleansegs (nilfs->ns_sufile);up_read (&NILFS_MDT (nilfs->ns_dat)->mi_sem); -return snprintf (buf,PAGE_SIZE ,"%lu\n" , ncleansegs); +return sysfs_emit (buf,"%lu\n" , ncleansegs); } static ssize_t
@@ -395,7 +395,7 @@ nilfs_segments_dirty_segments_show(struct nilfs_segments_attr *attr,return err; } -return snprintf (buf,PAGE_SIZE ,"%llu\n" , sustat.ss_ndirtysegs); +return sysfs_emit (buf,"%llu\n" , sustat.ss_ndirtysegs); } static const char segments_readme_str[] =
@@ -411,7 +411,7 @@ nilfs_segments_README_show(struct nilfs_segments_attr *attr,struct the_nilfs *nilfs, char *buf) { - return snprintf(buf, PAGE_SIZE, segments_readme_str); + return sysfs_emit(buf, segments_readme_str); }NILFS_SEGMENTS_RO_ATTR (segments_number);
@@ -448,7 +448,7 @@ nilfs_segctor_last_pseg_block_show(struct nilfs_segctor_attr *attr, last_pseg = nilfs->ns_last_pseg;spin_unlock (&nilfs->ns_last_segment_lock); -return snprintf (buf,PAGE_SIZE ,"%llu\n" , +return sysfs_emit (buf,"%llu\n" , (unsigned long long )last_pseg); }
@@ -463,7 +463,7 @@ nilfs_segctor_last_seg_sequence_show(struct nilfs_segctor_attr *attr, last_seq = nilfs->ns_last_seq;spin_unlock (&nilfs->ns_last_segment_lock); -return snprintf (buf,PAGE_SIZE ,"%llu\n" , last_seq); +return sysfs_emit (buf,"%llu\n" , last_seq); } static ssize_t
@@ -477,7 +477,7 @@ nilfs_segctor_last_seg_checkpoint_show(struct nilfs_segctor_attr *attr, last_cno = nilfs->ns_last_cno;spin_unlock (&nilfs->ns_last_segment_lock); -return snprintf (buf,PAGE_SIZE ,"%llu\n" , last_cno); +return sysfs_emit (buf,"%llu\n" , last_cno); } static ssize_t
@@ -491,7 +491,7 @@ nilfs_segctor_current_seg_sequence_show(struct nilfs_segctor_attr *attr, seg_seq = nilfs->ns_seg_seq;up_read (&nilfs->ns_segctor_sem); -return snprintf (buf,PAGE_SIZE ,"%llu\n" , seg_seq); +return sysfs_emit (buf,"%llu\n" , seg_seq); } static ssize_t
@@ -505,7 +505,7 @@ nilfs_segctor_current_last_full_seg_show(struct nilfs_segctor_attr *attr, segnum = nilfs->ns_segnum;up_read (&nilfs->ns_segctor_sem); -return snprintf (buf,PAGE_SIZE ,"%llu\n" , segnum); +return sysfs_emit (buf,"%llu\n" , segnum); } static ssize_t
@@ -519,7 +519,7 @@ nilfs_segctor_next_full_seg_show(struct nilfs_segctor_attr *attr, nextnum = nilfs->ns_nextnum;up_read (&nilfs->ns_segctor_sem); -return snprintf (buf,PAGE_SIZE ,"%llu\n" , nextnum); +return sysfs_emit (buf,"%llu\n" , nextnum); } static ssize_t
@@ -533,7 +533,7 @@ nilfs_segctor_next_pseg_offset_show(struct nilfs_segctor_attr *attr, pseg_offset = nilfs->ns_pseg_offset;up_read (&nilfs->ns_segctor_sem); -return snprintf (buf,PAGE_SIZE ,"%lu\n" , pseg_offset); +return sysfs_emit (buf,"%lu\n" , pseg_offset); } static ssize_t
@@ -547,7 +547,7 @@ nilfs_segctor_next_checkpoint_show(struct nilfs_segctor_attr *attr, cno = nilfs->ns_cno;up_read (&nilfs->ns_segctor_sem); -return snprintf (buf,PAGE_SIZE ,"%llu\n" , cno); +return sysfs_emit (buf,"%llu\n" , cno); } static ssize_t
@@ -575,7 +575,7 @@ nilfs_segctor_last_seg_write_time_secs_show(struct nilfs_segctor_attr *attr, ctime = nilfs->ns_ctime;up_read (&nilfs->ns_segctor_sem); -return snprintf (buf,PAGE_SIZE ,"%llu\n" , ctime); +return sysfs_emit (buf,"%llu\n" , ctime); } static ssize_t
@@ -603,7 +603,7 @@ nilfs_segctor_last_nongc_write_time_secs_show(struct nilfs_segctor_attr *attr, nongc_ctime = nilfs->ns_nongc_ctime;up_read (&nilfs->ns_segctor_sem); -return snprintf (buf,PAGE_SIZE ,"%llu\n" , nongc_ctime); +return sysfs_emit (buf,"%llu\n" , nongc_ctime); } static ssize_t
@@ -617,7 +617,7 @@ nilfs_segctor_dirty_data_blocks_count_show(struct nilfs_segctor_attr *attr, ndirtyblks =atomic_read (&nilfs->ns_ndirtyblks);up_read (&nilfs->ns_segctor_sem); -return snprintf (buf,PAGE_SIZE ,"%u\n" , ndirtyblks); +return sysfs_emit (buf,"%u\n" , ndirtyblks); } static const char segctor_readme_str[] =
@@ -654,7 +654,7 @@ static ssize_t nilfs_segctor_README_show(struct nilfs_segctor_attr *attr, struct the_nilfs *nilfs, char *buf) { - return snprintf(buf, PAGE_SIZE, segctor_readme_str); + return sysfs_emit(buf, segctor_readme_str); }NILFS_SEGCTOR_RO_ATTR (last_pseg_block);
@@ -723,7 +723,7 @@ nilfs_superblock_sb_write_time_secs_show(struct nilfs_superblock_attr *attr, sbwtime = nilfs->ns_sbwtime;up_read (&nilfs->ns_sem); -return snprintf (buf,PAGE_SIZE ,"%llu\n" , sbwtime); +return sysfs_emit (buf,"%llu\n" , sbwtime); } static ssize_t
@@ -737,7 +737,7 @@ nilfs_superblock_sb_write_count_show(struct nilfs_superblock_attr *attr, sbwcount = nilfs->ns_sbwcount;up_read (&nilfs->ns_sem); -return snprintf (buf,PAGE_SIZE ,"%u\n" , sbwcount); +return sysfs_emit (buf,"%u\n" , sbwcount); } static ssize_t
@@ -751,7 +751,7 @@ nilfs_superblock_sb_update_frequency_show(struct nilfs_superblock_attr *attr, sb_update_freq = nilfs->ns_sb_update_freq;up_read (&nilfs->ns_sem); -return snprintf (buf,PAGE_SIZE ,"%u\n" , sb_update_freq); +return sysfs_emit (buf,"%u\n" , sb_update_freq); } static ssize_t
@@ -799,7 +799,7 @@ static ssize_t nilfs_superblock_README_show(struct nilfs_superblock_attr *attr, struct the_nilfs *nilfs, char *buf) { - return snprintf(buf, PAGE_SIZE, sb_readme_str); + return sysfs_emit(buf, sb_readme_str); }NILFS_SUPERBLOCK_RO_ATTR (sb_write_time);
@@ -834,7 +834,7 @@ ssize_t nilfs_dev_revision_show(struct nilfs_dev_attr *attr,u32 major =le32_to_cpu (sbp[0 ]->s_rev_level);u16 minor =le16_to_cpu (sbp[0 ]->s_minor_rev_level); -return snprintf (buf,PAGE_SIZE ,"%d.%d\n" , major, minor); +return sysfs_emit (buf,"%d.%d\n" , major, minor); } static
@@ -842,7 +842,7 @@ ssize_t nilfs_dev_blocksize_show(struct nilfs_dev_attr *attr,struct the_nilfs *nilfs, char *buf) { - return snprintf(buf, PAGE_SIZE, "%u\n", nilfs->ns_blocksize); + return sysfs_emit(buf, "%u\n", nilfs->ns_blocksize); } static
@@ -853,7 +853,7 @@ ssize_t nilfs_dev_device_size_show(struct nilfs_dev_attr *attr,struct nilfs_super_block **sbp = nilfs->ns_sbp;u64 dev_size =le64_to_cpu (sbp[0 ]->s_dev_size); -return snprintf (buf,PAGE_SIZE ,"%llu\n" , dev_size); +return sysfs_emit (buf,"%llu\n" , dev_size); } static
@@ -864,7 +864,7 @@ ssize_t nilfs_dev_free_blocks_show(struct nilfs_dev_attr *attr,sector_t free_blocks =0 ;nilfs_count_free_blocks (nilfs, &free_blocks); -return snprintf (buf,PAGE_SIZE ,"%llu\n" , +return sysfs_emit (buf,"%llu\n" , (unsigned long long )free_blocks); }
@@ -875,7 +875,7 @@ ssize_t nilfs_dev_uuid_show(struct nilfs_dev_attr *attr, {struct nilfs_super_block **sbp = nilfs->ns_sbp; -return snprintf (buf,PAGE_SIZE ,"%pUb\n" , sbp[0 ]->s_uuid); +return sysfs_emit (buf,"%pUb\n" , sbp[0 ]->s_uuid); } static
@@ -903,7 +903,7 @@ static ssize_t nilfs_dev_README_show(struct nilfs_dev_attr *attr,struct the_nilfs *nilfs, char *buf) { - return snprintf(buf, PAGE_SIZE, dev_readme_str); + return sysfs_emit(buf, dev_readme_str); }NILFS_DEV_RO_ATTR (revision);
@@ -1047,7 +1047,7 @@ void nilfs_sysfs_delete_device_group(struct the_nilfs *nilfs)static ssize_t nilfs_feature_revision_show (struct kobject *kobj,struct attribute *attr,char *buf) { -return snprintf (buf,PAGE_SIZE ,"%d.%d\n" , +return sysfs_emit (buf,"%d.%d\n" ,NILFS_CURRENT_REV ,NILFS_MINOR_REV ); }
@@ -1060,7 +1060,7 @@ static ssize_t nilfs_feature_README_show(struct kobject *kobj,struct attribute *attr, char *buf) { - return snprintf(buf, PAGE_SIZE, features_readme_str); + return sysfs_emit(buf, features_readme_str); }NILFS_FEATURE_RO_ATTR (revision);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 194/214 nilfs2: protect references to superblock parameters exposed in sysfs
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ryusuke Konishi <[email protected]>
[ Upstream commit 683408258917541bdb294cd717c210a04381931e ]
The superblock buffers of nilfs2 can not only be overwritten at runtime for modifications/repairs, but they are also regularly swapped, replaced during resizing, and even abandoned when degrading to one side due to backing device issues. So, accessing them requires mutual exclusion using the reader/writer semaphore "nilfs->ns_sem".
Some sysfs attribute show methods read this superblock buffer without the necessary mutual exclusion, which can cause problems with pointer dereferencing and memory access, so fix it.
--- fs/nilfs2/sysfs.c | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-)
fs/nilfs2/sysfs.c +33 -10
@@ -830,9 +830,15 @@ ssize_t nilfs_dev_revision_show(struct nilfs_dev_attr *attr,struct the_nilfs *nilfs, char *buf) { - struct nilfs_super_block **sbp = nilfs->ns_sbp; -u32 major =le32_to_cpu (sbp[0 ]->s_rev_level); -u16 minor =le16_to_cpu (sbp[0 ]->s_minor_rev_level); + struct nilfs_super_block *raw_sb; +u32 major; +u16 minor; + +down_read (&nilfs->ns_sem); + raw_sb = nilfs->ns_sbp[0 ]; + major =le32_to_cpu (raw_sb->s_rev_level); + minor =le16_to_cpu (raw_sb->s_minor_rev_level); +up_read (&nilfs->ns_sem);return sysfs_emit (buf,"%d.%d\n" , major, minor); }
@@ -850,8 +856,13 @@ ssize_t nilfs_dev_device_size_show(struct nilfs_dev_attr *attr,struct the_nilfs *nilfs, char *buf) { - struct nilfs_super_block **sbp = nilfs->ns_sbp; -u64 dev_size =le64_to_cpu (sbp[0 ]->s_dev_size); + struct nilfs_super_block *raw_sb; +u64 dev_size; + +down_read (&nilfs->ns_sem); + raw_sb = nilfs->ns_sbp[0 ]; + dev_size =le64_to_cpu (raw_sb->s_dev_size); +up_read (&nilfs->ns_sem);return sysfs_emit (buf,"%llu\n" , dev_size); }
@@ -873,9 +884,15 @@ ssize_t nilfs_dev_uuid_show(struct nilfs_dev_attr *attr,struct the_nilfs *nilfs, char *buf) { - struct nilfs_super_block **sbp = nilfs->ns_sbp; + struct nilfs_super_block *raw_sb; +ssize_t len; -return sysfs_emit (buf,"%pUb\n" , sbp[0 ]->s_uuid); +down_read (&nilfs->ns_sem); + raw_sb = nilfs->ns_sbp[0 ]; + len =sysfs_emit (buf,"%pUb\n" , raw_sb->s_uuid); +up_read (&nilfs->ns_sem); + +return len; } static
@@ -883,10 +900,16 @@ ssize_t nilfs_dev_volume_name_show(struct nilfs_dev_attr *attr,struct the_nilfs *nilfs, char *buf) { - struct nilfs_super_block **sbp = nilfs->ns_sbp; + struct nilfs_super_block *raw_sb; +ssize_t len; + +down_read (&nilfs->ns_sem); + raw_sb = nilfs->ns_sbp[0 ]; + len =scnprintf (buf,sizeof (raw_sb->s_volume_name),"%s\n" , + raw_sb->s_volume_name); +up_read (&nilfs->ns_sem); -return scnprintf (buf,sizeof (sbp[0 ]->s_volume_name),"%s\n" , - sbp[0 ]->s_volume_name); +return len; } static const char dev_readme_str[] =
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 195/214 workqueue: wq_watchdog_touch is always called with valid CPU
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicholas Piggin <[email protected]>
[ Upstream commit 18e24deb1cc92f2068ce7434a94233741fbd7771 ]
Warn in the case it is called with cpu == -1. This does not appear to happen anywhere.
--- kernel/workqueue.c | 2 ++ 1 file changed, 2 insertions(+)
kernel/workqueue.c +2 -0
@@ -5937,6 +5937,8 @@ notrace void wq_watchdog_touch(int cpu) {if (cpu >=0 )per_cpu (wq_watchdog_touched_cpu, cpu) = jiffies; +else +WARN_ONCE (1 ,"%s should be called with valid CPU" , __func__); wq_watchdog_touched = jiffies; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 196/214 workqueue: Improve scalability of workqueue watchdog touch
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicholas Piggin <[email protected]>
[ Upstream commit 98f887f820c993e05a12e8aa816c80b8661d4c87 ]
On a ~2000 CPU powerpc system, hard lockups have been observed in the workqueue code when stop_machine runs (in this case due to CPU hotplug). This is due to lots of CPUs spinning in multi_cpu_stop, calling touch_nmi_watchdog() which ends up calling wq_watchdog_touch(). wq_watchdog_touch() writes to the global variable wq_watchdog_touched, and that can find itself in the same cacheline as other important workqueue data, which slows down operations to the point of lockups.
In the case of the following abridged trace, worker_pool_idr was in the hot line, causing the lockups to always appear at idr_find.
watchdog: CPU 1125 self-detected hard LOCKUP @ idr_find
Call Trace: get_work_pool __queue_work call_timer_fn run_timer_softirq __do_softirq do_softirq_own_stack irq_exit timer_interrupt decrementer_common_virt * interrupt: 900 (timer) at multi_cpu_stop multi_cpu_stop cpu_stopper_thread smpboot_thread_fn kthread
Fix this by having wq_watchdog_touch() only write to the line if the last time a touch was recorded exceeds 1/4 of the watchdog threshold.
--- kernel/workqueue.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
kernel/workqueue.c +8 -2
@@ -5935,12 +5935,18 @@ static void wq_watchdog_timer_fn(struct timer_list *unused) notrace void wq_watchdog_touch(int cpu) { +unsigned long thresh =READ_ONCE (wq_watchdog_thresh) *HZ ; +unsigned long touch_ts =READ_ONCE (wq_watchdog_touched); +unsigned long now = jiffies; +if (cpu >=0 ) -per_cpu (wq_watchdog_touched_cpu, cpu) = jiffies; +per_cpu (wq_watchdog_touched_cpu, cpu) = now;else WARN_ONCE (1 ,"%s should be called with valid CPU" , __func__); - wq_watchdog_touched = jiffies; +/* Don't unnecessarily store to global cacheline */ +if (time_after (now, touch_ts + thresh /4 )) +WRITE_ONCE (wq_watchdog_touched, jiffies); }static void wq_watchdog_set_thresh (unsigned long thresh)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 197/214 ACPI: processor: Return an error if acpi_processor_get_info() fails in processor_add()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonathan Cameron <[email protected]>
[ Upstream commit fadf231f0a06a6748a7fc4a2c29ac9ef7bca6bfd ]
Rafael observed [1] that returning 0 from processor_add() will result in acpi_default_enumeration() being called which will attempt to create a platform device, but that makes little sense when the processor is known to be not available. So just return the error code from acpi_processor_get_info() instead.
--- drivers/acpi/acpi_processor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/acpi_processor.c +1 -1
@@ -373,7 +373,7 @@ static int acpi_processor_add(struct acpi_device *device, result =acpi_processor_get_info (device);if (result)/* Processor is not physically present or unavailable */ -return 0 ; +return result;BUG_ON (pr->id >= nr_cpu_ids);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 198/214 ACPI: processor: Fix memory leaks in error paths of processor_add()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonathan Cameron <[email protected]>
[ Upstream commit 47ec9b417ed9b6b8ec2a941cd84d9de62adc358a ]
If acpi_processor_get_info() returned an error, pr and the associated pr->throttling.shared_cpu_map were leaked.
The unwind code was in the wrong order wrt to setup, relying on some unwind actions having no affect (clearing variables that were never set etc). That makes it harder to reason about so reorder and add appropriate labels to only undo what was actually set up in the first place.
--- drivers/acpi/acpi_processor.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
drivers/acpi/acpi_processor.c +8 -7
@@ -373,7 +373,7 @@ static int acpi_processor_add(struct acpi_device *device, result =acpi_processor_get_info (device);if (result)/* Processor is not physically present or unavailable */ -return result; + goto err_clear_driver_data;BUG_ON (pr->id >= nr_cpu_ids);
@@ -388,7 +388,7 @@ static int acpi_processor_add(struct acpi_device *device,"BIOS reported wrong ACPI id %d for the processor\n" , pr->id);/* Give up, but do not abort the namespace scan. */ - goto err; + goto err_clear_driver_data; }/* * processor_device_array is not cleared on errors to allow buggy BIOS
@@ -400,12 +400,12 @@ static int acpi_processor_add(struct acpi_device *device, dev =get_cpu_device (pr->id);if (!dev) { result = -ENODEV ; - goto err; + goto err_clear_per_cpu; } result =acpi_bind_one (dev, device);if (result) - goto err; + goto err_clear_per_cpu; pr->dev = dev;
@@ -416,10 +416,11 @@ static int acpi_processor_add(struct acpi_device *device,dev_err (dev,"Processor driver could not be attached\n" );acpi_unbind_one (dev); - err: -free_cpumask_var (pr->throttling.shared_cpu_map); - device->driver_data =NULL ; + err_clear_per_cpu:per_cpu (processors, pr->id) =NULL ; + err_clear_driver_data: + device->driver_data =NULL ; +free_cpumask_var (pr->throttling.shared_cpu_map); err_free_pr:kfree (pr);return result;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 199/214 arm64: acpi: Move get_cpu_for_acpi_id() to a header
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: James Morse <[email protected]>
[ Upstream commit 8d34b6f17b9ac93faa2791eb037dcb08bdf755de ]
ACPI identifies CPUs by UID. get_cpu_for_acpi_id() maps the ACPI UID to the Linux CPU number.
The helper to retrieve this mapping is only available in arm64's NUMA code.
Move it to live next to get_acpi_id_for_cpu().
--- arch/arm64/include/asm/acpi.h | 11 +++++++++++ arch/arm64/kernel/acpi_numa.c | 11 ----------- 2 files changed, 11 insertions(+), 11 deletions(-)
arch/arm64/include/asm/acpi.h +11 -0
@@ -97,6 +97,17 @@ static inline u32 get_acpi_id_for_cpu(unsigned int cpu)return acpi_cpu_get_madt_gicc (cpu)->uid; } +static inline int get_cpu_for_acpi_id (u32 uid) +{ +int cpu; + +for (cpu =0 ; cpu < nr_cpu_ids; cpu++) +if (uid ==get_acpi_id_for_cpu (cpu)) +return cpu; + +return -EINVAL ; +} +static inline void arch_fix_phys_package_id (int num,u32 slot) { }void __init acpi_init_cpus (void );int apei_claim_sea (struct pt_regs *regs);
arch/arm64/kernel/acpi_numa.c +0 -11
@@ -34,17 +34,6 @@ int __init acpi_numa_get_nid(unsigned int cpu)return acpi_early_node_map[cpu]; } -static inline int get_cpu_for_acpi_id (u32 uid) -{ -int cpu; - -for (cpu =0 ; cpu < nr_cpu_ids; cpu++) -if (uid ==get_acpi_id_for_cpu (cpu)) -return cpu; - -return -EINVAL ; -} -static int __init acpi_parse_gicc_pxm (union acpi_subtable_headers *header,const unsigned long end) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 200/214 arm64: acpi: Harden get_cpu_for_acpi_id() against missing CPU entry
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonathan Cameron <[email protected]>
[ Upstream commit 2488444274c70038eb6b686cba5f1ce48ebb9cdd ]
In a review discussion of the changes to support vCPU hotplug where a check was added on the GICC being enabled if was online, it was noted that there is need to map back to the cpu and use that to index into a cpumask. As such, a valid ID is needed.
If an MPIDR check fails in acpi_map_gic_cpu_interface() it is possible for the entry in cpu_madt_gicc[cpu] == NULL. This function would
then cause a NULL pointer dereference. Whilst a path to trigger
this has not been established, harden this caller against the possibility.
--- arch/arm64/include/asm/acpi.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
arch/arm64/include/asm/acpi.h +2 -1
@@ -102,7 +102,8 @@ static inline int get_cpu_for_acpi_id(u32 uid)int cpu;for (cpu =0 ; cpu < nr_cpu_ids; cpu++) -if (uid ==get_acpi_id_for_cpu (cpu)) +if (acpi_cpu_get_madt_gicc (cpu) && + uid ==get_acpi_id_for_cpu (cpu))return cpu;return -EINVAL ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 201/214 nvmet-tcp: fix kernel crash if commands allocation fails
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maurizio Lombardi <[email protected]>
[ Upstream commit 5572a55a6f830ee3f3a994b6b962a5c327d28cb3 ]
If the commands allocation fails in nvmet_tcp_alloc_cmds() the kernel crashes in nvmet_tcp_release_queue_work() because of a NULL pointer dereference.
nvmet: failed to install queue 0 cntlid 1 ret 6
Unable to handle kernel NULL pointer dereference at
virtual address 0000000000000008Fix the bug by setting queue->nr_cmds to zero in case nvmet_tcp_alloc_cmd() fails.
--- drivers/nvme/target/tcp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/nvme/target/tcp.c +3 -1
@@ -1819,8 +1819,10 @@ static u16 nvmet_tcp_install_queue(struct nvmet_sq *sq) } queue->nr_cmds = sq->size *2 ; -if (nvmet_tcp_alloc_cmds (queue)) +if (nvmet_tcp_alloc_cmds (queue)) { + queue->nr_cmds =0 ;return NVME_SC_INTERNAL ; + }return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 202/214 ASoC: sunxi: sun4i-i2s: fix LRCLK polarity in i2s mode
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matteo Martelli <[email protected]>
[ Upstream commit 3e83957e8dd7433a69116780d9bad217b00913ea ]
This fixes the LRCLK polarity for sun8i-h3 and sun50i-h6 in i2s mode which was wrongly inverted.
The LRCLK was being set in reversed logic compared to the DAI format:
inverted LRCLK for SND_SOC_DAIFMT_IB_NF and SND_SOC_DAIFMT_NB_NF; normal LRCLK for SND_SOC_DAIFMT_IB_IF and SND_SOC_DAIFMT_NB_IF. Such reversed logic applies properly for DSP_A, DSP_B, LEFT_J and RIGHT_J modes but not for I2S mode, for which the LRCLK signal results reversed to what expected on the bus. The issue is due to a misinterpretation of the LRCLK polarity bit of the H3 and H6 i2s controllers. Such bit in this case does not mean "0 => normal" or "1 => inverted" according to the expected bus operation, but it means "0 => frame starts on low edge" and "1 => frame starts on high edge" (from the User Manuals).
This commit fixes the LRCLK polarity by setting the LRCLK polarity bit according to the selected bus mode and renames the LRCLK polarity bit definition to avoid further confusion.
--- sound/soc/sunxi/sun4i-i2s.c | 143 ++++++++++++++++++------------------ 1 file changed, 73 insertions(+), 70 deletions(-)
sound/soc/sunxi/sun4i-i2s.c +73 -70
@@ -100,8 +100,8 @@#define SUN8I_I2S_CTRL_MODE_PCM (0 << 4)#define SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK BIT(19) -#define SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED (1 << 19) -#define SUN8I_I2S_FMT0_LRCLK_POLARITY_NORMAL (0 << 19) +#define SUN8I_I2S_FMT0_LRCLK_POLARITY_START_HIGH (1 << 19) +#define SUN8I_I2S_FMT0_LRCLK_POLARITY_START_LOW (0 << 19)#define SUN8I_I2S_FMT0_LRCK_PERIOD_MASK GENMASK(17, 8)#define SUN8I_I2S_FMT0_LRCK_PERIOD (period) ((period - 1) << 8)#define SUN8I_I2S_FMT0_BCLK_POLARITY_MASK BIT(7)
@@ -709,65 +709,37 @@ static int sun4i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,static int sun8i_i2s_set_soc_fmt (const struct sun4i_i2s *i2s,unsigned int fmt) { -u32 mode, val; +u32 mode, lrclk_pol, bclk_pol, val;u8 offset; -/* -* DAI clock polarity -* -* The setup for LRCK contradicts the datasheet, but under a -* scope it's clear that the LRCK polarity is reversed -* compared to the expected polarity on the bus. -*/ -switch (fmt &SND_SOC_DAIFMT_INV_MASK ) { -case SND_SOC_DAIFMT_IB_IF : -/* Invert both clocks */ - val =SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED ; -break ; -case SND_SOC_DAIFMT_IB_NF : -/* Invert bit clock */ - val =SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED | -SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED ; -break ; -case SND_SOC_DAIFMT_NB_IF : -/* Invert frame clock */ - val =0 ; -break ; -case SND_SOC_DAIFMT_NB_NF : - val =SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED ; -break ; -default : -return -EINVAL ; - } - -regmap_update_bits (i2s->regmap,SUN4I_I2S_FMT0_REG , -SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK | -SUN8I_I2S_FMT0_BCLK_POLARITY_MASK , - val); -/* DAI Mode */ switch (fmt &SND_SOC_DAIFMT_FORMAT_MASK ) {case SND_SOC_DAIFMT_DSP_A : + lrclk_pol =SUN8I_I2S_FMT0_LRCLK_POLARITY_START_HIGH ; mode =SUN8I_I2S_CTRL_MODE_PCM ; offset =1 ;break ;case SND_SOC_DAIFMT_DSP_B : + lrclk_pol =SUN8I_I2S_FMT0_LRCLK_POLARITY_START_HIGH ; mode =SUN8I_I2S_CTRL_MODE_PCM ; offset =0 ;break ;case SND_SOC_DAIFMT_I2S : + lrclk_pol =SUN8I_I2S_FMT0_LRCLK_POLARITY_START_LOW ; mode =SUN8I_I2S_CTRL_MODE_LEFT ; offset =1 ;break ;case SND_SOC_DAIFMT_LEFT_J : + lrclk_pol =SUN8I_I2S_FMT0_LRCLK_POLARITY_START_HIGH ; mode =SUN8I_I2S_CTRL_MODE_LEFT ; offset =0 ;break ;case SND_SOC_DAIFMT_RIGHT_J : + lrclk_pol =SUN8I_I2S_FMT0_LRCLK_POLARITY_START_HIGH ; mode =SUN8I_I2S_CTRL_MODE_RIGHT ; offset =0 ;break ;
@@ -785,6 +757,35 @@ static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,SUN8I_I2S_TX_CHAN_OFFSET_MASK , SUN8I_I2S_TX_CHAN_OFFSET(offset)); +/* DAI clock polarity */ + bclk_pol =SUN8I_I2S_FMT0_BCLK_POLARITY_NORMAL ; + +switch (fmt &SND_SOC_DAIFMT_INV_MASK ) { +case SND_SOC_DAIFMT_IB_IF : +/* Invert both clocks */ + lrclk_pol ^=SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK ; + bclk_pol =SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED ; +break ; +case SND_SOC_DAIFMT_IB_NF : +/* Invert bit clock */ + bclk_pol =SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED ; +break ; +case SND_SOC_DAIFMT_NB_IF : +/* Invert frame clock */ + lrclk_pol ^=SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK ; +break ; +case SND_SOC_DAIFMT_NB_NF : +/* No inversion */ +break ; +default : +return -EINVAL ; + } + +regmap_update_bits (i2s->regmap,SUN4I_I2S_FMT0_REG , +SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK | +SUN8I_I2S_FMT0_BCLK_POLARITY_MASK , + lrclk_pol | bclk_pol); +/* DAI clock master masks */ switch (fmt &SND_SOC_DAIFMT_MASTER_MASK ) {case SND_SOC_DAIFMT_CBS_CFS :
@@ -816,65 +817,37 @@ static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,static int sun50i_h6_i2s_set_soc_fmt (const struct sun4i_i2s *i2s,unsigned int fmt) { -u32 mode, val; +u32 mode, lrclk_pol, bclk_pol, val;u8 offset; -/* -* DAI clock polarity -* -* The setup for LRCK contradicts the datasheet, but under a -* scope it's clear that the LRCK polarity is reversed -* compared to the expected polarity on the bus. -*/ -switch (fmt &SND_SOC_DAIFMT_INV_MASK ) { -case SND_SOC_DAIFMT_IB_IF : -/* Invert both clocks */ - val =SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED ; -break ; -case SND_SOC_DAIFMT_IB_NF : -/* Invert bit clock */ - val =SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED | -SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED ; -break ; -case SND_SOC_DAIFMT_NB_IF : -/* Invert frame clock */ - val =0 ; -break ; -case SND_SOC_DAIFMT_NB_NF : - val =SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED ; -break ; -default : -return -EINVAL ; - } - -regmap_update_bits (i2s->regmap,SUN4I_I2S_FMT0_REG , -SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK | -SUN8I_I2S_FMT0_BCLK_POLARITY_MASK , - val); -/* DAI Mode */ switch (fmt &SND_SOC_DAIFMT_FORMAT_MASK ) {case SND_SOC_DAIFMT_DSP_A : + lrclk_pol =SUN8I_I2S_FMT0_LRCLK_POLARITY_START_HIGH ; mode =SUN8I_I2S_CTRL_MODE_PCM ; offset =1 ;break ;case SND_SOC_DAIFMT_DSP_B : + lrclk_pol =SUN8I_I2S_FMT0_LRCLK_POLARITY_START_HIGH ; mode =SUN8I_I2S_CTRL_MODE_PCM ; offset =0 ;break ;case SND_SOC_DAIFMT_I2S : + lrclk_pol =SUN8I_I2S_FMT0_LRCLK_POLARITY_START_LOW ; mode =SUN8I_I2S_CTRL_MODE_LEFT ; offset =1 ;break ;case SND_SOC_DAIFMT_LEFT_J : + lrclk_pol =SUN8I_I2S_FMT0_LRCLK_POLARITY_START_HIGH ; mode =SUN8I_I2S_CTRL_MODE_LEFT ; offset =0 ;break ;case SND_SOC_DAIFMT_RIGHT_J : + lrclk_pol =SUN8I_I2S_FMT0_LRCLK_POLARITY_START_HIGH ; mode =SUN8I_I2S_CTRL_MODE_RIGHT ; offset =0 ;break ;
@@ -892,6 +865,36 @@ static int sun50i_h6_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET_MASK , SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET(offset)); +/* DAI clock polarity */ + bclk_pol =SUN8I_I2S_FMT0_BCLK_POLARITY_NORMAL ; + +switch (fmt &SND_SOC_DAIFMT_INV_MASK ) { +case SND_SOC_DAIFMT_IB_IF : +/* Invert both clocks */ + lrclk_pol ^=SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK ; + bclk_pol =SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED ; +break ; +case SND_SOC_DAIFMT_IB_NF : +/* Invert bit clock */ + bclk_pol =SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED ; +break ; +case SND_SOC_DAIFMT_NB_IF : +/* Invert frame clock */ + lrclk_pol ^=SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK ; +break ; +case SND_SOC_DAIFMT_NB_NF : +/* No inversion */ +break ; +default : +return -EINVAL ; + } + +regmap_update_bits (i2s->regmap,SUN4I_I2S_FMT0_REG , +SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK | +SUN8I_I2S_FMT0_BCLK_POLARITY_MASK , + lrclk_pol | bclk_pol); + +/* DAI clock master masks */ switch (fmt &SND_SOC_DAIFMT_MASTER_MASK ) {case SND_SOC_DAIFMT_CBS_CFS :
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 203/214 drm/i915/fence: Mark debug_fence_init_onstack() with __maybe_unused
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andy Shevchenko <[email protected]>
[ Upstream commit fcd9e8afd546f6ced378d078345a89bf346d065e ]
When debug_fence_init_onstack() is unused (CONFIG_DRM_I915_SELFTEST=n), it prevents kernel builds with clang, make W=1 and CONFIG_WERROR=y:
.../i915_sw_fence.c:97:20: error: unused function 'debug_fence_init_onstack' [-Werror,-Wunused-function]
97 | static inline void debug_fence_init_onstack(struct i915_sw_fence *fence)
| ^~~~~~~~~~~~~~~~~~~~~~~~
Fix this by marking debug_fence_init_onstack() with __maybe_unused.
See also commit 6863f5643dd7 ("kbuild: allow Clang to find unused static inline functions for W=1 build").
--- drivers/gpu/drm/i915/i915_sw_fence.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/i915_sw_fence.c +2 -2
@@ -49,7 +49,7 @@ static inline void debug_fence_init(struct i915_sw_fence *fence)debug_object_init (fence, &i915_sw_fence_debug_descr); } -static inline void debug_fence_init_onstack (struct i915_sw_fence *fence) +static inline __maybe_unused void debug_fence_init_onstack (struct i915_sw_fence *fence) {debug_object_init_on_stack (fence, &i915_sw_fence_debug_descr); }
@@ -92,7 +92,7 @@ static inline void debug_fence_init(struct i915_sw_fence *fence) { } -static inline void debug_fence_init_onstack (struct i915_sw_fence *fence) +static inline __maybe_unused void debug_fence_init_onstack (struct i915_sw_fence *fence) { }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 204/214 drm/i915/fence: Mark debug_fence_free() with __maybe_unused
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andy Shevchenko <[email protected]>
[ Upstream commit f99999536128b14b5d765a9982763b5134efdd79 ]
When debug_fence_free() is unused (CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS=n), it prevents kernel builds with clang, make W=1 and CONFIG_WERROR=y:
.../i915_sw_fence.c:118:20: error: unused function 'debug_fence_free' [-Werror,-Wunused-function]
118 | static inline void debug_fence_free(struct i915_sw_fence *fence)
| ^~~~~~~~~~~~~~~~
Fix this by marking debug_fence_free() with __maybe_unused.
See also commit 6863f5643dd7 ("kbuild: allow Clang to find unused static inline functions for W=1 build").
--- drivers/gpu/drm/i915/i915_sw_fence.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/i915_sw_fence.c +2 -2
@@ -75,7 +75,7 @@ static inline void debug_fence_destroy(struct i915_sw_fence *fence)debug_object_destroy (fence, &i915_sw_fence_debug_descr); } -static inline void debug_fence_free (struct i915_sw_fence *fence) +static inline __maybe_unused void debug_fence_free (struct i915_sw_fence *fence) {debug_object_free (fence, &i915_sw_fence_debug_descr);smp_wmb ();/* flush the change in state before reallocation */
@@ -113,7 +113,7 @@ static inline void debug_fence_destroy(struct i915_sw_fence *fence) { } -static inline void debug_fence_free (struct i915_sw_fence *fence) +static inline __maybe_unused void debug_fence_free (struct i915_sw_fence *fence) { }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 205/214 gpio: rockchip: fix OF node leak in probe()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Kozlowski <[email protected]>
[ Upstream commit adad2e460e505a556f5ea6f0dc16fe95e62d5d76 ]
Driver code is leaking OF node reference from of_get_parent() in probe().
--- drivers/gpio/gpio-rockchip.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpio/gpio-rockchip.c +1 -0
@@ -708,6 +708,7 @@ static int rockchip_gpio_probe(struct platform_device *pdev)return -ENODEV ; pctldev =of_pinctrl_get (pctlnp); +of_node_put (pctlnp);if (!pctldev)return -EPROBE_DEFER ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 206/214 net: more strict VIRTIO_NET_HDR_GSO_UDP_L4 validation
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Willem de Bruijn <[email protected]>
[ Upstream commit fc8b2a619469378717e7270d2a4e1ef93c585f7a ]
Syzbot reported two new paths to hit an internal WARNING using the new virtio gso type VIRTIO_NET_HDR_GSO_UDP_L4.
RIP: 0010:skb_checksum_help+0x4a2/0x600 net/core/dev.c:3260
skb len=64521 gso_size=344and
RIP: 0010:skb_warn_bad_offload+0x118/0x240 net/core/dev.c:3262
Older virtio types have historically had loose restrictions, leading to many entirely impractical fuzzer generated packets causing problems deep in the kernel stack. Ideally, we would have had strict validation for all types from the start.
New virtio types can have tighter validation. Limit UDP GSO packets inserted via virtio to the same limits imposed by the UDP_SEGMENT socket interface:
1. must use checksum offload
2. checksum offload matches UDP header
3. no more segments than UDP_MAX_SEGMENTS
4. UDP GSO does not take modifier flags, notably SKB_GSO_TCP_ECN
--- include/linux/virtio_net.h | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-)
include/linux/virtio_net.h +16 -3
@@ -3,8 +3,8 @@#define _LINUX_VIRTIO_NET_H#include <linux/if_vlan.h> +#include <linux/udp.h> #include <uapi/linux/tcp.h> -#include <uapi/linux/udp.h> #include <uapi/linux/virtio_net.h> static inline bool virtio_net_hdr_match_proto (__be16 protocol,__u8 gso_type)
@@ -155,9 +155,22 @@ retry:unsigned int nh_off = p_off;struct skb_shared_info *shinfo =skb_shinfo (skb); -/* UFO may not include transport header in gso_size. */ -if (gso_type &SKB_GSO_UDP ) +switch (gso_type & ~SKB_GSO_TCP_ECN ) { +case SKB_GSO_UDP : +/* UFO may not include transport header in gso_size. */ nh_off -= thlen; +break ; +case SKB_GSO_UDP_L4 : +if (!(hdr->flags &VIRTIO_NET_HDR_F_NEEDS_CSUM )) +return -EINVAL ; +if (skb->csum_offset != offsetof(struct udphdr , check)) +return -EINVAL ; +if (skb->len - p_off > gso_size *UDP_MAX_SEGMENTS ) +return -EINVAL ; +if (gso_type !=SKB_GSO_UDP_L4 ) +return -EINVAL ; +break ; + }/* Kernel has a special handling for GSO_BY_FRAGS. */ if (gso_size ==GSO_BY_FRAGS )
Greg Kroah-Hartman
maintainerPATCH 207/214 net: change maximum number of UDP segments to 128
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuri Benditovich <[email protected]>
[ Upstream commit 1382e3b6a3500c245e5278c66d210c02926f804f ]
The commit fc8b2a619469
("net: more strict VIRTIO_NET_HDR_GSO_UDP_L4 validation") adds check of potential number of UDP segments vs UDP_MAX_SEGMENTS in linux/virtio_net.h.
After this change certification test of USO guest-to-guest transmit on Windows driver for virtio-net device fails, for example with packet size of ~64K and mss of 536 bytes. In general the USO should not be more restrictive than TSO. Indeed, in case of unreasonably small mss a lot of segments can cause queue overflow and packet loss on the destination. Limit of 128 segments is good for any practical purpose, with minimal meaningful mss of 536 the maximal UDP packet will be divided to ~120 segments.
The number of segments for UDP packets is validated vs UDP_MAX_SEGMENTS also in udp.c (v4,v6), this does not affect quest-to-guest path but does affect packets sent to host, for example.
It is important to mention that UDP_MAX_SEGMENTS is kernel-only define and not available to user mode socket applications. In order to request MSS smaller than MTU the applications just uses setsockopt with SOL_UDP and UDP_SEGMENT and there is no limitations on socket API level.
[5.15-stable: fix conflict with neighboring but unrelated code from
e2a4392b61f6 ("udp: introduce udp->udp_flags")--- include/linux/udp.h | 2 +- tools/testing/selftests/net/udpgso.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
include/linux/udp.h +1 -1
@@ -94,7 +94,7 @@ struct udp_sock {int forward_deficit; }; -#define UDP_MAX_SEGMENTS (1 << 6UL) +#define UDP_MAX_SEGMENTS (1 << 7UL)static inline struct udp_sock *udp_sk (const struct sock *sk) {
tools/testing/selftests/net/udpgso.c +1 -1
@@ -34,7 +34,7 @@#endif #ifndef UDP_MAX_SEGMENTS -#define UDP_MAX_SEGMENTS (1 << 6UL) +#define UDP_MAX_SEGMENTS (1 << 7UL)#endif #define CONST_MTU_TEST 1500
Greg Kroah-Hartman
maintainerPATCH 208/214 gso: fix dodgy bit handling for GSO_UDP_L4
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yan Zhai <[email protected]>
[ Upstream commit 9840036786d90cea11a90d1f30b6dc003b34ee67 ]
Commit 1fd54773c267 ("udp: allow header check for dodgy GSO_UDP_L4 packets.") checks DODGY bit for UDP, but for packets that can be fed directly to the device after gso_segs reset, it actually falls through to fragmentation:
https://lore.kernel.org/all/CAJPywTKDdjtwkLVUW6LRA2FU912qcDmQOQGt2WaDo28KzYDg+A@mail.gmail.com/
This change restores the expected behavior of GSO_UDP_L4 packets.
--- net/ipv4/udp_offload.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
net/ipv4/udp_offload.c +10 -3
@@ -272,13 +272,20 @@ struct sk_buff *__udp_gso_segment(struct__sum16 check;__be16 newlen; -if (skb_shinfo (gso_skb)->gso_type &SKB_GSO_FRAGLIST ) -return __udp_gso_segment_list (gso_skb, features, is_ipv6); - mss =skb_shinfo (gso_skb)->gso_size;if (gso_skb->len <=sizeof (*uh) + mss)return ERR_PTR (-EINVAL ); +if (skb_gso_ok (gso_skb, features |NETIF_F_GSO_ROBUST )) { +/* Packet is from an untrusted source, reset gso_segs. */ +skb_shinfo (gso_skb)->gso_segs =DIV_ROUND_UP (gso_skb->len -sizeof (*uh), + mss); +return NULL ; + } + +if (skb_shinfo (gso_skb)->gso_type &SKB_GSO_FRAGLIST ) +return __udp_gso_segment_list (gso_skb, features, is_ipv6); +skb_pull (gso_skb,sizeof (*uh));/* clear destructor to avoid skb_segment assigning it to tail */
Greg Kroah-Hartman
maintainerPATCH 209/214 net: drop bad gso csum_start and offset in virtio_net_hdr
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Willem de Bruijn <[email protected]>
[ Upstream commit 89add40066f9ed9abe5f7f886fe5789ff7e0c50e ]
Tighten csum_start and csum_offset checks in virtio_net_hdr_to_skb for GSO packets.
The function already checks that a checksum requested with VIRTIO_NET_HDR_F_NEEDS_CSUM is in skb linear. But for GSO packets this might not hold for segs after segmentation.
Syzkaller demonstrated to reach this warning in skb_checksum_help
offset = skb_checksum_start_offset(skb); ret = -EINVAL; if (WARN_ON_ONCE(offset >= skb_headlen(skb)))
By injecting a TSO packet:
WARNING: CPU: 1 PID: 3539 at net/core/dev.c:3284 skb_checksum_help+0x3d0/0x5b0 ip_do_fragment+0x209/0x1b20 net/ipv4/ip_output.c:774 ip_finish_output_gso net/ipv4/ip_output.c:279 [inline] __ip_finish_output+0x2bd/0x4b0 net/ipv4/ip_output.c:301 iptunnel_xmit+0x50c/0x930 net/ipv4/ip_tunnel_core.c:82 ip_tunnel_xmit+0x2296/0x2c70 net/ipv4/ip_tunnel.c:813 __gre_xmit net/ipv4/ip_gre.c:469 [inline] ipgre_xmit+0x759/0xa60 net/ipv4/ip_gre.c:661 __netdev_start_xmit include/linux/netdevice.h:4850 [inline] netdev_start_xmit include/linux/netdevice.h:4864 [inline] xmit_one net/core/dev.c:3595 [inline] dev_hard_start_xmit+0x261/0x8c0 net/core/dev.c:3611 __dev_queue_xmit+0x1b97/0x3c90 net/core/dev.c:4261 packet_snd net/packet/af_packet.c:3073 [inline]
The geometry of the bad input packet at tcp_gso_segment:
[ 52.003050][ T8403] skb len=12202 headroom=244 headlen=12093 tailroom=0 [ 52.003050][ T8403] mac=(168,24) mac_len=24 net=(192,52) trans=244 [ 52.003050][ T8403] shinfo(txflags=0 nr_frags=1 gso(size=1552 type=3 segs=0)) [ 52.003050][ T8403] csum(0x60000c7 start=199 offset=1536
ip_summed=3 complete_sw=0 valid=0 level=0)
Mitigate with stricter input validation.
csum_offset: for GSO packets, deduce the correct value from gso_type. This is already done for USO. Extend it to TSO. Let UFO be:
udp[46]_ufo_fragment ignores these fields and always computes the checksum in software.
csum_start: finding the real offset requires parsing to the transport header. Do not add a parser, use existing segmentation parsing. Thanks to SKB_GSO_DODGY, that also catches bad packets that are hw offloaded. Again test both TSO and USO. Do not test UFO for the above reason, and do not test UDP tunnel offload.
GSO packet are almost always CHECKSUM_PARTIAL. USO packets may be CHECKSUM_NONE since commit 10154dbded6d6 ("udp: Allow GSO transmit from devices with no checksum offload"), but then still these fields are initialized correctly in udp4_hwcsum/udp6_hwcsum_outgoing. So no need to test for ip_summed == CHECKSUM_PARTIAL first.
This revises an existing fix mentioned in the Fixes tag, which broke small packets with GSO offload, as detected by kselftests.
--- include/linux/virtio_net.h | 16 +++++----------- net/ipv4/tcp_offload.c | 3 +++ net/ipv4/udp_offload.c | 4 ++++ 3 files changed, 12 insertions(+), 11 deletions(-)
include/linux/virtio_net.h +5 -11
@@ -51,7 +51,6 @@ static inline int virtio_net_hdr_to_skb(unsigned int thlen =0 ;unsigned int p_off =0 ;unsigned int ip_proto; -u64 ret, remainder, gso_size;if (hdr->gso_type !=VIRTIO_NET_HDR_GSO_NONE ) {switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN ) {
@@ -88,16 +87,6 @@ static inline int virtio_net_hdr_to_skb(u32 off =__virtio16_to_cpu (little_endian, hdr->csum_offset);u32 needed = start +max_t (u32, thlen, off +sizeof (__sum16)); -if (hdr->gso_size) { - gso_size =__virtio16_to_cpu (little_endian, hdr->gso_size); - ret =div64_u64_rem (skb->len, gso_size, &remainder); -if (!(ret && (hdr->gso_size > needed) && - ((remainder > needed) || (remainder ==0 )))) { -return -EINVAL ; - } -skb_shinfo (skb)->tx_flags |=SKBFL_SHARED_FRAG ; - } -if (!pskb_may_pull (skb, needed))return -EINVAL ;
@@ -170,6 +159,11 @@ retry:if (gso_type !=SKB_GSO_UDP_L4 )return -EINVAL ;break ; +case SKB_GSO_TCPV4 : +case SKB_GSO_TCPV6 : +if (skb->csum_offset != offsetof(struct tcphdr , check)) +return -EINVAL ; +break ; }/* Kernel has a special handling for GSO_BY_FRAGS. */
net/ipv4/tcp_offload.c +3 -0
@@ -71,6 +71,9 @@ struct sk_buff *tcp_gso_segment(struct sif (thlen <sizeof (*th)) goto out; +if (unlikely (skb_checksum_start (skb) !=skb_transport_header (skb))) + goto out; +if (!pskb_may_pull (skb, thlen)) goto out;
net/ipv4/udp_offload.c +4 -0
@@ -276,6 +276,10 @@ struct sk_buff *__udp_gso_segment(structif (gso_skb->len <=sizeof (*uh) + mss)return ERR_PTR (-EINVAL ); +if (unlikely (skb_checksum_start (gso_skb) != +skb_transport_header (gso_skb))) +return ERR_PTR (-EINVAL ); +if (skb_gso_ok (gso_skb, features |NETIF_F_GSO_ROBUST )) {/* Packet is from an untrusted source, reset gso_segs. */ skb_shinfo(gso_skb)->gso_segs = DIV_ROUND_UP(gso_skb->len - sizeof(*uh),
Greg Kroah-Hartman
maintainerPATCH 210/214 x86/mm: Fix PTI for i386 some more
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Gleixner <[email protected]>
commit c48b5a4cf3125adb679e28ef093f66ff81368d05 upstream.
So it turns out that we have to do two passes of pti_clone_entry_text(), once before initcalls, such that device and late initcalls can use user-mode-helper / modprobe and once after free_initmem() / mark_readonly().
Now obviously mark_readonly() can cause PMD splits, and pti_clone_pgtable() doesn't like that much.
Allow the late clone to split PMDs so that pagetables stay in sync.
--- arch/x86/mm/pti.c | 45 +++++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 16 deletions(-)
arch/x86/mm/pti.c +29 -16
@@ -241,7 +241,7 @@ static pmd_t *pti_user_pagetable_walk_pm* * Returns a pointer to a PTE on success, or NULL on failure. */ -static pte_t *pti_user_pagetable_walk_pte (unsigned long address) +static pte_t *pti_user_pagetable_walk_pte (unsigned long address,bool late_text) {gfp_t gfp = (GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO);pmd_t *pmd;
@@ -251,10 +251,15 @@ static pte_t *pti_user_pagetable_walk_ptif (!pmd)return NULL ; -/* We can't do anything sensible if we hit a large mapping. */ +/* Large PMD mapping found */ if (pmd_large (*pmd)) { -WARN_ON (1 ); -return NULL ; +/* Clear the PMD if we hit a large mapping from the first round */ +if (late_text) { +set_pmd (pmd,__pmd (0 )); + }else { +WARN_ON_ONCE (1 ); +return NULL ; + } }if (pmd_none (*pmd)) {
@@ -283,7 +288,7 @@ static void __init pti_setup_vsyscall(voif (!pte ||WARN_ON (level !=PG_LEVEL_4K ) ||pte_none (*pte))return ; - target_pte =pti_user_pagetable_walk_pte (VSYSCALL_ADDR ); + target_pte =pti_user_pagetable_walk_pte (VSYSCALL_ADDR , false);if (WARN_ON (!target_pte))return ;
@@ -301,7 +306,7 @@ enum pti_clone_level {static void pti_clone_pgtable (unsigned long start,unsigned long end, -enum pti_clone_level level) +enum pti_clone_level level,bool late_text) {unsigned long addr;
@@ -390,7 +395,7 @@ pti_clone_pgtable(unsigned long start, ureturn ;/* Allocate PTE in the user page-table */ - target_pte =pti_user_pagetable_walk_pte (addr); + target_pte =pti_user_pagetable_walk_pte (addr, late_text);if (WARN_ON (!target_pte))return ;
@@ -452,7 +457,7 @@ static void __init pti_clone_user_sharedphys_addr_t pa =per_cpu_ptr_to_phys ((void *)va);pte_t *target_pte; - target_pte =pti_user_pagetable_walk_pte (va); + target_pte =pti_user_pagetable_walk_pte (va, false);if (WARN_ON (!target_pte))return ;
@@ -475,7 +480,7 @@ static void __init pti_clone_user_shared start =CPU_ENTRY_AREA_BASE ; end = start + (PAGE_SIZE *CPU_ENTRY_AREA_PAGES ); - pti_clone_pgtable(start, end, PTI_CLONE_PMD); + pti_clone_pgtable(start, end, PTI_CLONE_PMD, false); }#endif /* CONFIG_X86_64 */
@@ -492,11 +497,11 @@ static void __init pti_setup_espfix64(vo/* * Clone the populated PMDs of the entry text and force it RO. */ -static void pti_clone_entry_text (void ) +static void pti_clone_entry_text (bool late) {pti_clone_pgtable ((unsigned long ) __entry_text_start, (unsigned long ) __entry_text_end, -PTI_LEVEL_KERNEL_IMAGE ); +PTI_LEVEL_KERNEL_IMAGE , late); }/*
@@ -571,7 +576,7 @@ static void pti_clone_kernel_text(void)* pti_set_kernel_image_nonglobal() did to clear the * global bit. */ -pti_clone_pgtable (start, end_clone,PTI_LEVEL_KERNEL_IMAGE ); +pti_clone_pgtable (start, end_clone,PTI_LEVEL_KERNEL_IMAGE , false);/* * pti_clone_pgtable() will set the global bit in any PMDs
@@ -638,8 +643,15 @@ void __init pti_init(void)/* Undo all global bits from the init pagetables in head_64.S: */ pti_set_kernel_image_nonglobal (); +/* Replace some of the global bits just for shared entry text: */ -pti_clone_entry_text (); +/* +* This is very early in boot. Device and Late initcalls can do +* modprobe before free_initmem() and mark_readonly(). This +* pti_clone_entry_text() allows those user-mode-helpers to function, +* but notably the text is still RW. +*/ +pti_clone_entry_text (false);pti_setup_espfix64 ();pti_setup_vsyscall (); }
@@ -656,10 +668,11 @@ void pti_finalize(void)if (!boot_cpu_has (X86_FEATURE_PTI ))return ;/* -* We need to clone everything (again) that maps parts of the -* kernel image. +* This is after free_initmem() (all initcalls are done) and we've done +* mark_readonly(). Text is now NX which might've split some PMDs +* relative to the early clone. */ -pti_clone_entry_text (); +pti_clone_entry_text (true);pti_clone_kernel_text ();debug_checkwx_user ();
Greg Kroah-Hartman
maintainerPATCH 211/214 net, sunrpc: Remap EPERM in case of connection failure in xs_tcp_setup_socket
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Borkmann <[email protected]>
commit 626dfed5fa3bfb41e0dffd796032b555b69f9cde upstream.
When using a BPF program on kernel_connect(), the call can return -EPERM. This causes xs_tcp_setup_socket() to loop forever, filling up the syslog and causing the kernel to potentially freeze up.
Neil suggested:
This will propagate -EPERM up into other layers which might not be ready to handle it. It might be safer to map EPERM to an error we would be more likely to expect from the network system - such as ECONNREFUSED or ENETDOWN.
ECONNREFUSED as error seems reasonable. For programs setting a different error can be out of reach (see handling in 4fbac77d2d09) in particular on kernels which do not have f10d05966196 ("bpf: Make BPF_PROG_RUN_ARRAY return -err instead of allow boolean"), thus given that it is better to simply remap for consistent behavior. UDP does handle EPERM in xs_udp_send_request().
--- net/sunrpc/xprtsock.c | 7 +++++++ 1 file changed, 7 insertions(+)
net/sunrpc/xprtsock.c +7 -0
@@ -2335,6 +2335,13 @@ static void xs_tcp_setup_socket(struct wcase -EALREADY :xprt_unlock_connect (xprt, transport);return ; +case -EPERM : +/* Happens, for instance, if a BPF program is preventing +* the connect. Remap the error so upper layers can better +* deal with it. +*/ + status = -ECONNREFUSED ; + fallthrough;case -EINVAL :/* Happens, for instance, if the user specified a link * local IPv6 address without a scope-id.
Greg Kroah-Hartman
maintainerPATCH 212/214 btrfs: fix race between direct IO write and fsync when using same fd
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana <[email protected]>
commit cd9253c23aedd61eb5ff11f37a36247cd46faf86 upstream.
If we have 2 threads that are using the same file descriptor and one of them is doing direct IO writes while the other is doing fsync, we have a race where we can end up either:
1) Attempt a fsync without holding the inode's lock, triggering an assertion failures when assertions are enabled;
2) Do an invalid memory access from the fsync task because the file private points to memory allocated on stack by the direct IO task and it may be used by the fsync task after the stack was destroyed.
The race happens like this:
1) A user space program opens a file descriptor with O_DIRECT;
2) The program spawns 2 threads using libpthread for example;
3) One of the threads uses the file descriptor to do direct IO writes, while the other calls fsync using the same file descriptor.
4) Call task A the thread doing direct IO writes and task B the thread doing fsyncs;
5) Task A does a direct IO write, and at btrfs_direct_write() sets the file's private to an on stack allocated private with the member 'fsync_skip_inode_lock' set to true;
6) Task B enters btrfs_sync_file() and sees that there's a private structure associated to the file which has 'fsync_skip_inode_lock' set to true, so it skips locking the inode's VFS lock;
7) Task A completes the direct IO write, and resets the file's private to NULL since it had no prior private and our private was stack allocated. Then it unlocks the inode's VFS lock;
8) Task B enters btrfs_get_ordered_extents_for_logging(), then the assertion that checks the inode's VFS lock is held fails, since task B never locked it and task A has already unlocked it.
The stack trace produced is the following:
assertion failed: inode_is_locked(&inode->vfs_inode), in fs/btrfs/ordered-data.c:983
------------[ cut here ]------------
kernel BUG at fs/btrfs/ordered-data.c:983!
Oops: invalid opcode: 0000 [#1] PREEMPT SMP PTI
CPU: 9 PID: 5072 Comm: worker Tainted: G U OE 6.10.5-1-default #1 openSUSE Tumbleweed 69f48d427608e1c09e60ea24c6c55e2ca1b049e8
Hardware name: Acer Predator PH315-52/Covini_CFS, BIOS V1.12 07/28/2020
RIP: 0010:btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs]
Code: 50 d6 86 c0 e8 (...)
RSP: 0018:ffff9e4a03dcfc78 EFLAGS: 00010246
RAX: 0000000000000054 RBX: ffff9078a9868e98 RCX: 0000000000000000
RDX: 0000000000000000 RSI: ffff907dce4a7800 RDI: ffff907dce4a7800
RBP: ffff907805518800 R08: 0000000000000000 R09: ffff9e4a03dcfb38
R10: ffff9e4a03dcfb30 R11: 0000000000000003 R12: ffff907684ae7800
R13: 0000000000000001 R14: ffff90774646b600 R15: 0000000000000000
FS: 00007f04b96006c0(0000) GS:ffff907dce480000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f32acbfc000 CR3: 00000001fd4fa005 CR4: 00000000003726f0
Call Trace:
<TASK>
? __die_body.cold+0x14/0x24
? die+0x2e/0x50
? do_trap+0xca/0x110
? do_error_trap+0x6a/0x90
? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
? exc_invalid_op+0x50/0x70
? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
? asm_exc_invalid_op+0x1a/0x20
? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
btrfs_sync_file+0x21a/0x4d0 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
? __seccomp_filter+0x31d/0x4f0
__x64_sys_fdatasync+0x4f/0x90
do_syscall_64+0x82/0x160
? do_futex+0xcb/0x190
? __x64_sys_futex+0x10e/0x1d0
? switch_fpu_return+0x4f/0xd0
? syscall_exit_to_user_mode+0x72/0x220
? do_syscall_64+0x8e/0x160
? syscall_exit_to_user_mode+0x72/0x220
? do_syscall_64+0x8e/0x160
? syscall_exit_to_user_mode+0x72/0x220
? do_syscall_64+0x8e/0x160
? syscall_exit_to_user_mode+0x72/0x220
? do_syscall_64+0x8e/0x160
entry_SYSCALL_64_after_hwframe+0x76/0x7eAnother problem here is if task B grabs the private pointer and then uses it after task A has finished, since the private was allocated in the stack of task A, it results in some invalid memory access with a hard to predict result.
This issue, triggering the assertion, was observed with QEMU workloads by two users in the Link tags below.
Fix this by not relying on a file's private to pass information to fsync that it should skip locking the inode and instead pass this information through a special value stored in current->journal_info. This is safe because in the relevant section of the direct IO write path we are not holding a transaction handle, so current->journal_info is NULL.
The following C program triggers the issue:
$ cat repro.c /* Get the O_DIRECT definition. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <stdint.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <pthread.h>
static int fd;
static ssize_t do_write(int fd, const void *buf, size_t count, off_t offset)
{
while (count > 0) {
ssize_t ret; ret = pwrite(fd, buf, count, offset);
if (ret < 0) {
if (errno == EINTR)
continue;
return ret;
}
count -= ret;
buf += ret;
}
return 0;}
static void *fsync_loop(void *arg)
{
while (1) {
int ret; ret = fsync(fd);
if (ret != 0) {
perror("Fsync failed");
exit(6);
}
}}
int main(int argc, char *argv[])
{
long pagesize;
void *write_buf;
pthread_t fsyncer;
int ret; if (argc != 2) {
fprintf(stderr, "Use: %s <file path>\n", argv[0]);
return 1;
}
fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC | O_DIRECT, 0666);
if (fd == -1) {
perror("Failed to open/create file");
return 1;
}
pagesize = sysconf(_SC_PAGE_SIZE);
if (pagesize == -1) {
perror("Failed to get page size");
return 2;
}
ret = posix_memalign(&write_buf, pagesize, pagesize);
if (ret) {
perror("Failed to allocate buffer");
return 3;
}
ret = pthread_create(&fsyncer, NULL, fsync_loop, NULL);
if (ret != 0) {
fprintf(stderr, "Failed to create writer thread: %d\n", ret);
return 4;
}
while (1) {
ret = do_write(fd, write_buf, pagesize, 0);
if (ret != 0) {
perror("Write failed");
exit(5);
}
}
return 0;}
$ mkfs.btrfs -f /dev/sdi $ mount /dev/sdi /mnt/sdi $ timeout 10 ./repro /mnt/sdi/foo
Usually the race is triggered within less than 1 second. A test case for fstests will follow soon.
--- fs/btrfs/ctree.h | 1 - fs/btrfs/file.c | 25 ++++++++++--------------- fs/btrfs/transaction.h | 6 ++++++ 3 files changed, 16 insertions(+), 16 deletions(-)
fs/btrfs/ctree.h +0 -1
@@ -1383,7 +1383,6 @@ struct btrfs_drop_extents_args {struct btrfs_file_private {void *filldir_buf;u64 last_index; -bool fsync_skip_inode_lock; };
fs/btrfs/file.c +10 -15
@@ -1992,13 +1992,6 @@ again:if (IS_ERR_OR_NULL (dio)) { err =PTR_ERR_OR_ZERO (dio); }else { -struct btrfs_file_private stack_private = {0 }; -struct btrfs_file_private *private; -const bool have_private = (file->private_data !=NULL ); - -if (!have_private) - file->private_data = &stack_private; -/* * If we have a synchoronous write, we must make sure the fsync * triggered by the iomap_dio_complete() call below doesn't
@@ -2007,13 +2000,10 @@ again:* partial writes due to the input buffer (or parts of it) not * being already faulted in. */ - private = file->private_data; - private->fsync_skip_inode_lock = true; +ASSERT (current->journal_info ==NULL ); + current->journal_info =BTRFS_TRANS_DIO_WRITE_STUB ; err =iomap_dio_complete (dio); - private->fsync_skip_inode_lock = false; - -if (!have_private) - file->private_data =NULL ; + current->journal_info =NULL ; }/* No increment (+=) because iomap returns a cumulative value. */
@@ -2195,7 +2185,6 @@ static inline bool skip_inode_logging(co*/ int btrfs_sync_file (struct file *file,loff_t start,loff_t end,int datasync) { -struct btrfs_file_private *private = file->private_data;struct dentry *dentry =file_dentry (file);struct inode *inode =d_inode (dentry);struct btrfs_fs_info *fs_info =btrfs_sb (inode->i_sb);
@@ -2205,7 +2194,13 @@ int btrfs_sync_file(struct file *file, lint ret =0 , err;u64 len;bool full_sync; -const bool skip_ilock = (private ? private->fsync_skip_inode_lock : false); +bool skip_ilock = false; + +if (current->journal_info ==BTRFS_TRANS_DIO_WRITE_STUB ) { + skip_ilock = true; + current->journal_info =NULL ; +lockdep_assert_held (&inode->i_rwsem); + }trace_btrfs_sync_file (file, datasync);
fs/btrfs/transaction.h +6 -0
@@ -11,6 +11,12 @@#include "delayed-ref.h" #include "ctree.h" +/* +* Signal that a direct IO write is in progress, to avoid deadlock for sync +* direct IO writes when fsync is called during the direct IO write path. +*/ +#define BTRFS_TRANS_DIO_WRITE_STUB ((void *) 1) +enum btrfs_trans_state {TRANS_STATE_RUNNING ,TRANS_STATE_COMMIT_START ,
Greg Kroah-Hartman
maintainerPATCH 213/214 memcg: protect concurrent access to mem_cgroup_idr
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shakeel Butt <[email protected]>
commit 9972605a238339b85bd16b084eed5f18414d22db upstream.
Commit 73f576c04b94 ("mm: memcontrol: fix cgroup creation failure after many small jobs") decoupled the memcg IDs from the CSS ID space to fix the cgroup creation failures. It introduced IDR to maintain the memcg ID space. The IDR depends on external synchronization mechanisms for modifications. For the mem_cgroup_idr, the idr_alloc() and idr_replace() happen within css callback and thus are protected through cgroup_mutex from concurrent modifications. However idr_remove() for mem_cgroup_idr was not protected against concurrency and can be run concurrently for different memcgs when they hit their refcnt to zero. Fix that.
We have been seeing list_lru based kernel crashes at a low frequency in our fleet for a long time. These crashes were in different part of list_lru code including list_lru_add(), list_lru_del() and reparenting code. Upon further inspection, it looked like for a given object (dentry and inode), the super_block's list_lru didn't have list_lru_one for the memcg of that object. The initial suspicions were either the object is not allocated through kmem_cache_alloc_lru() or somehow memcg_list_lru_alloc() failed to allocate list_lru_one() for a memcg but returned success. No evidence were found for these cases.
Looking more deeply, we started seeing situations where valid memcg's id is not present in mem_cgroup_idr and in some cases multiple valid memcgs have same id and mem_cgroup_idr is pointing to one of them. So, the most reasonable explanation is that these situations can happen due to race between multiple idr_remove() calls or race between idr_alloc()/idr_replace() and idr_remove(). These races are causing multiple memcgs to acquire the same ID and then offlining of one of them would cleanup list_lrus on the system for all of them. Later access from other memcgs to the list_lru cause crashes due to missing list_lru_one.
[ Adapted over commit be740503ed03 ("mm: memcontrol: fix cannot alloc the
maximum memcg ID") and 6f0df8e16eb5 ("memcontrol: ensure memcg acquired by id is properly set up") both are not in the tree ]
--- mm/memcontrol.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-)
mm/memcontrol.c +20 -3
@@ -5083,11 +5083,28 @@ static struct cftype mem_cgroup_legacy_f*/ static DEFINE_IDR (mem_cgroup_idr); +static DEFINE_SPINLOCK (memcg_idr_lock); + +static int mem_cgroup_alloc_id (void ) +{ +int ret; + +idr_preload (GFP_KERNEL ); +spin_lock (&memcg_idr_lock); + ret =idr_alloc (&mem_cgroup_idr,NULL ,1 ,MEM_CGROUP_ID_MAX +1 , +GFP_NOWAIT ); +spin_unlock (&memcg_idr_lock); +idr_preload_end (); +return ret; +}static void mem_cgroup_id_remove (struct mem_cgroup *memcg) {if (memcg->id.id >0 ) { +spin_lock (&memcg_idr_lock);idr_remove (&mem_cgroup_idr, memcg->id.id); +spin_unlock (&memcg_idr_lock); + memcg->id.id =0 ; } }
@@ -5201,9 +5218,7 @@ static struct mem_cgroup *mem_cgroup_allif (!memcg)return ERR_PTR (error); - memcg->id.id =idr_alloc (&mem_cgroup_idr,NULL , -1 ,MEM_CGROUP_ID_MAX , -GFP_KERNEL ); + memcg->id.id =mem_cgroup_alloc_id ();if (memcg->id.id <0 ) { error = memcg->id.id; goto fail;
@@ -5244,7 +5259,9 @@ static struct mem_cgroup *mem_cgroup_allINIT_LIST_HEAD (&memcg->deferred_split_queue.split_queue); memcg->deferred_split_queue.split_queue_len =0 ;#endif +spin_lock (&memcg_idr_lock);idr_replace (&mem_cgroup_idr, memcg, memcg->id.id); +spin_unlock (&memcg_idr_lock);return memcg; fail:mem_cgroup_id_remove (memcg);
Greg Kroah-Hartman
maintainerPATCH 214/214 udp: fix receiving fraglist GSO packets
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Fietkau <[email protected]>
commit b128ed5ab27330deeeaf51ea8bb69f1442a96f7f upstream.
When assembling fraglist GSO packets, udp4_gro_complete does not set skb->csum_start, which makes the extra validation in __udp_gso_segment fail.
--- net/ipv4/udp_offload.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/ipv4/udp_offload.c +2 -1
@@ -277,7 +277,8 @@ struct sk_buff *__udp_gso_segment(structreturn ERR_PTR (-EINVAL );if (unlikely (skb_checksum_start (gso_skb) != -skb_transport_header (gso_skb))) +skb_transport_header (gso_skb) && + !(skb_shinfo (gso_skb)->gso_type &SKB_GSO_FRAGLIST )))return ERR_PTR (-EINVAL );if (skb_gso_ok (gso_skb, features |NETIF_F_GSO_ROBUST )) {
Hi Greg,
Quoted 20 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.15.167 release. There are 214 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 Thu, 12 Sep 2024 09:25:22 +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/v5.x/stable-review/patch-5.15.167-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.15.y
and the diffstat can be found below.thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
...
Quoted 2 lines
Satya Priya Kakitapalli <[email protected]>
clk: qcom: clk-alpha-pll: Updateset_ratefor Zonda PLL
The above change is causing build issues on both mainline and now with stable. There is a fix in the works [0] but has not been merged yet. For kernels such as 5.15.y where this driver is enabled, the build fails for us with ...
drivers/clk/qcom/clk-alpha-pll.o: In function `clk_zonda_pll_set_rate':
clk-alpha-pll.c:(.text+0x2f90): undefined reference to `__aeabi_uldivmod'
Jon
[0] https://lore.kernel.org/linux-clk/[email protected]/
Signature · 1 line
nvpublic
Greg Kroah-Hartman
maintainerQuoted 29 lines · Jon Hunter
Hi Greg,
Quoted 20 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.15.167 release. There are 214 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 Thu, 12 Sep 2024 09:25:22 +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/v5.x/stable-review/patch-5.15.167-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.15.y
and the diffstat can be found below.thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:...
Quoted 2 lines
Satya Priya Kakitapalli <[email protected]>
clk: qcom: clk-alpha-pll: Updateset_ratefor Zonda PLL
Quoted 8 lines
The above change is causing build issues on both mainline and now with stable. There is a fix in the works [0] but has not been merged yet. For kernels such as 5.15.y where this driver is enabled, the build fails for us with ...
drivers/clk/qcom/clk-alpha-pll.o: In function `clk_zonda_pll_set_rate':
clk-alpha-pll.c:(.text+0x2f90): undefined reference to `__aeabi_uldivmod'
I'll go drop this from all branches and just wait for the fix to be send and then someone can send both of them to us for inclusion.
thanks,
greg k-h
Quoted 4 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.15.167 release. There are 214 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.
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.15.167 release. There are 214 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 Thu, 12 Sep 2024 09:25:22 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.15.167-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.15.y
and the diffstat can be found below.thanks,
greg k-h
On ARCH_BRCMSTB using 32-bit and 64-bit ARM kernels, build tested on BMIPS_GENERIC:
Signature · 1 line
Florian
Quoted 7 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.15.167 release. There are 214 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 Thu, 12 Sep 2024 09:25:22 +0000. Anything received after that time might be too late.
Hi Greg,
No problems seen on x86_64 and aarch64 with our testing.
Thanks,
Harshit
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.15.167 release. There are 214 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 Thu, 12 Sep 2024 09:25:22 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 9 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.15.167-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.15.y
and the diffstat can be found below.thanks,
greg k-h
I am seeing a modpost error when I install the kernel. Looks
ERROR: modpost: module ad7606_par uses symbol ad7606_reset from namespace IIO_AD7606, but does not import it. make[1]: *** [scripts/Makefile.modpost:133: modules-only.symvers] Error 1
make[1]: *** Deleting file 'modules-only.symvers'
make: *** [Makefile:1825: modules] Error 2
I am seeing a modpost error when I install the kernel. Looks like thge following commit is the problem.
Quoted 4 lines
Guillaume Stols <[email protected]>
iio: adc: ad7606: remove frstdata check for serial mode
thanks,
-- Shuah
Greg Kroah-Hartman
maintainerQuoted 20 lines · Shuah Khan
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.15.167 release. There are 214 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 Thu, 12 Sep 2024 09:25:22 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 9 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.15.167-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.15.y
and the diffstat can be found below.thanks,
greg k-h
Quoted 12 lines
I am seeing a modpost error when I install the kernel. Looks
ERROR: modpost: modulead7606_paruses symbolad7606_resetfrom namespaceIIO_AD7606, but does not import it. make[1]: *** [scripts/Makefile.modpost:133: modules-only.symvers] Error 1
make[1]: *** Deleting file 'modules-only.symvers'
make: *** [Makefile:1825: modules] Error 2I am seeing a modpost error when I install the kernel. Looks like thge following commit is the problem.
Quoted 3 lines
Guillaume Stols <[email protected]>
iio: adc: ad7606: remove frstdata check for serial mode
Will drop this, thanks!
greg k-h
Quoted 10 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.15.167 release. There are 214 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 Thu, 12 Sep 2024 09:25:22 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.15.167-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.15.y
and the diffstat can be found below.thanks,
greg k-h
Results from Linaro’s test farm.
No regressions on arm64, arm, x86_64, and i386.
## Build
* kernel: 5.15.167-rc1
* git: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git
* git commit: 72253b6b4643a28e11448f1ee2d2f0fbda027130
* git describe: v5.15.166-215-g72253b6b4643
* test details:
https://qa-reports.linaro.org/lkft/linux-stable-rc-linux-5.15.y/build/v5.15.166-215-g72253b6b4643
## Test Regressions (compared to v5.15.165-216-g36422b23d6d0)
## Metric Regressions (compared to v5.15.165-216-g36422b23d6d0)
## Test Fixes (compared to v5.15.165-216-g36422b23d6d0)
## Metric Fixes (compared to v5.15.165-216-g36422b23d6d0)
## Test result summary
total: 278874, pass: 232368, fail: 5633, skip: 40510, xfail: 363
## Build Summary
* arc: 15 total, 15 passed, 0 failed
* arm: 306 total, 306 passed, 0 failed
* arm64: 87 total, 87 passed, 0 failed
* i386: 69 total, 69 passed, 0 failed
* mips: 66 total, 66 passed, 0 failed
* parisc: 9 total, 9 passed, 0 failed
* powerpc: 72 total, 72 passed, 0 failed
* riscv: 18 total, 18 passed, 0 failed
* s390: 27 total, 27 passed, 0 failed
* sh: 30 total, 30 passed, 0 failed
* sparc: 18 total, 18 passed, 0 failed
* x86_64: 75 total, 75 passed, 0 failed
## Test suites summary
* boot
* kselftest-arm64
* kselftest-breakpoints
* kselftest-capabilities
* kselftest-cgroup
* kselftest-clone3
* kselftest-core
* kselftest-cpu-hotplug
* kselftest-cpufreq
* kselftest-efivarfs
* kselftest-exec
* kselftest-filesystems
* kselftest-filesystems-binderfs
* kselftest-filesystems-epoll
* kselftest-firmware
* kselftest-fpu
* kselftest-ftrace
* kselftest-futex
* kselftest-gpio
* kselftest-intel_pstate
* kselftest-ipc
* kselftest-kcmp
* kselftest-livepatch
* kselftest-membarrier
* kselftest-memfd
* kselftest-mincore
* kselftest-mqueue
* kselftest-net
* kselftest-net-mptcp
* kselftest-openat2
* kselftest-ptrace
* kselftest-rseq
* kselftest-rtc
* kselftest-seccomp
* kselftest-sigaltstack
* kselftest-size
* kselftest-tc-testing
* kselftest-timers
* kselftest-tmpfs
* kselftest-tpm2
* kselftest-user_events
* kselftest-vDSO
* kselftest-x86
* kunit
* kvm-unit-tests
* libgpiod
* libhugetlbfs
* log-parser-boot
* log-parser-test
* ltp-commands
* ltp-containers
* ltp-controllers
* ltp-cpuhotplug
* ltp-crypto
* ltp-cve
* ltp-dio
* ltp-fcntl-locktests
* ltp-fs
* ltp-fs_bind
* ltp-fs_perms_simple
* ltp-hugetlb
* ltp-ipc
* ltp-math
* ltp-mm
* ltp-nptl
* ltp-pty
* ltp-sched
* ltp-smoke
* ltp-syscalls
* ltp-tracing
* perf
* rcutorture
--
Linaro LKFT
https://lkft.linaro.org