6.6.120-rc1 review
Subsystems (6)
Greg Kroah-Hartman
maintainerPATCH 568/737 leds: leds-lp50xx: Enable chip before any communication
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Hitz <[email protected]>
commit 434959618c47efe9e5f2e20f4a850caac4f6b823 upstream.
If a GPIO is used to control the chip's enable pin, it needs to be pulled high before any i2c communication is attempted.
Currently, the enable GPIO handling is not correct.
Assume the enable GPIO is low when the probe function is entered. In this case the device is in SHUTDOWN mode and does not react to i2c commands.
During probe the following sequence happens:
1. The call to lp50xx_reset() on line 548 has no effect as i2c is not possible yet.
2. Then - on line 552 - lp50xx_enable_disable() is called. As "priv->enable_gpio“ has not yet been initialized, setting the GPIO has no effect. Also the i2c enable command is not executed as the device is still in SHUTDOWN.
3. On line 556 the call to lp50xx_probe_dt() finally parses the rest of
the DT and the configured priv->enable_gpio is set up.
As a result the device is still in SHUTDOWN mode and not ready for operation.
Split lp50xx_enable_disable() into distinct enable and disable functions to enforce correct ordering between enable_gpio manipulations and i2c commands.
Read enable_gpio configuration from DT before attempting to manipulate enable_gpio.
Add delays to observe correct wait timing after manipulating enable_gpio and before any i2c communication.
--- drivers/leds/leds-lp50xx.c | 55 ++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 15 deletions(-)
drivers/leds/leds-lp50xx.c +40 -15
@@ -52,6 +52,12 @@#define LP50XX_SW_RESET 0xff#define LP50XX_CHIP_EN BIT(6) +#define LP50XX_CHIP_DISABLE 0x00 +#define LP50XX_START_TIME_US 500 +#define LP50XX_RESET_TIME_US 3 + +#define LP50XX_EN_GPIO_LOW 0 +#define LP50XX_EN_GPIO_HIGH 1/* There are 3 LED outputs per bank */ #define LP50XX_LEDS_PER_MODULE 3
@@ -374,19 +380,42 @@ static int lp50xx_reset(struct lp50xx *preturn regmap_write (priv->regmap, priv->chip_info->reset_reg,LP50XX_SW_RESET ); } -static int lp50xx_enable_disable (struct lp50xx *priv,int enable_disable) +static int lp50xx_enable (struct lp50xx *priv) {int ret; - ret =gpiod_direction_output (priv->enable_gpio, enable_disable); +if (priv->enable_gpio) { + ret =gpiod_direction_output (priv->enable_gpio,LP50XX_EN_GPIO_HIGH ); +if (ret) +return ret; + +udelay (LP50XX_START_TIME_US ); + } + + ret =lp50xx_reset (priv);if (ret)return ret; -if (enable_disable) -return regmap_write (priv->regmap,LP50XX_DEV_CFG0 ,LP50XX_CHIP_EN ); -else -return regmap_write (priv->regmap,LP50XX_DEV_CFG0 ,0 ); +return regmap_write (priv->regmap,LP50XX_DEV_CFG0 ,LP50XX_CHIP_EN ); +} +static int lp50xx_disable (struct lp50xx *priv) +{ +int ret; + + ret =regmap_write (priv->regmap,LP50XX_DEV_CFG0 ,LP50XX_CHIP_DISABLE ); +if (ret) +return ret; + +if (priv->enable_gpio) { + ret =gpiod_direction_output (priv->enable_gpio,LP50XX_EN_GPIO_LOW ); +if (ret) +return ret; + +udelay (LP50XX_RESET_TIME_US ); + } + +return 0 ; } static int lp50xx_probe_leds(struct fwnode_handle *child, struct lp50xx *priv,
@@ -453,6 +482,10 @@ static int lp50xx_probe_dt(struct lp50xxreturn dev_err_probe (priv->dev,PTR_ERR (priv->enable_gpio),"Failed to get enable GPIO\n" ); + ret =lp50xx_enable (priv); +if (ret) +return ret; + priv->regulator =devm_regulator_get (priv->dev,"vled" );if (IS_ERR (priv->regulator)) priv->regulator =NULL ;
@@ -559,14 +592,6 @@ static int lp50xx_probe(struct i2c_clienreturn ret; } - ret =lp50xx_reset (led); -if (ret) -return ret; - - ret =lp50xx_enable_disable (led,1 ); -if (ret) -return ret; -return lp50xx_probe_dt (led); }
@@ -575,7 +600,7 @@ static void lp50xx_remove(struct i2c_clistruct lp50xx *led =i2c_get_clientdata (client);int ret; - ret =lp50xx_enable_disable (led,0 ); + ret =lp50xx_disable (led);if (ret)dev_err (led->dev,"Failed to disable chip\n" );
Greg Kroah-Hartman
maintainerPATCH 569/737 clk: samsung: exynos-clkout: Assign .num before accessing .hws
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nathan Chancellor <[email protected]>
commit cf33f0b7df13685234ccea7be7bfe316b60db4db upstream.
Commit f316cdff8d67 ("clk: Annotate struct clk_hw_onecell_data with __counted_by") annotated the hws member of 'struct clk_hw_onecell_data' with __counted_by, which informs the bounds sanitizer (UBSAN_BOUNDS) about the number of elements in .hws[], so that it can warn when .hws[] is accessed out of bounds. As noted in that change, the __counted_by member must be initialized with the number of elements before the first array access happens, otherwise there will be a warning from each access prior to the initialization because the number of elements is zero. This occurs in exynos_clkout_probe() due to .num being assigned after .hws[] has been accessed:
UBSAN: array-index-out-of-bounds in drivers/clk/samsung/clk-exynos-clkout.c:178:18 index 0 is out of range for type 'clk_hw *[*]'
Move the .num initialization to before the first access of .hws[], clearing up the warning.
--- drivers/clk/samsung/clk-exynos-clkout.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/clk/samsung/clk-exynos-clkout.c +1 -1
@@ -168,6 +168,7 @@ static int exynos_clkout_probe(struct pl clkout->mux.shift =EXYNOS_CLKOUT_MUX_SHIFT ; clkout->mux.lock = &clkout->slock; + clkout->data.num =EXYNOS_CLKOUT_NR_CLKS ; clkout->data.hws[0] = clk_hw_register_composite(NULL, "clkout", parent_names, parent_count, &clkout->mux.hw, &clk_mux_ops, NULL, NULL, &clkout->gate.hw,
@@ -178,7 +179,6 @@ static int exynos_clkout_probe(struct pl goto err_unmap; } - clkout->data.num =EXYNOS_CLKOUT_NR_CLKS ; ret =of_clk_add_hw_provider (clkout->np, of_clk_hw_onecell_get, &clkout->data);if (ret) goto err_clk_unreg;
Greg Kroah-Hartman
maintainerPATCH 570/737 mfd: altera-sysmgr: Fix device leak on sysmgr regmap lookup
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit ccb7cd3218e48665f3c7e19eede0da5f069c323d upstream.
Make sure to drop the reference taken to the sysmgr platform device when retrieving its driver data.
Note that holding a reference to a device does not prevent its driver data from going away.
--- drivers/mfd/altera-sysmgr.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/mfd/altera-sysmgr.c +2 -0
@@ -117,6 +117,8 @@ struct regmap *altr_sysmgr_regmap_lookup sysmgr =dev_get_drvdata (dev); +put_device (dev); +return sysmgr->regmap; }EXPORT_SYMBOL_GPL (altr_sysmgr_regmap_lookup_by_phandle);
Greg Kroah-Hartman
maintainerPATCH 571/737 mfd: max77620: Fix potential IRQ chip conflict when probing two devices
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Kozlowski <[email protected]>
commit 2bac49bad1f3553cc3b3bfb22cc194e9bd9e8427 upstream.
MAX77620 is most likely always a single device on the board, however nothing stops board designers to have two of them, thus same device driver could probe twice. Or user could manually try to probing second time.
Device driver is not ready for that case, because it allocates statically 'struct regmap_irq_chip' as non-const and stores during probe in 'irq_drv_data' member a pointer to per-probe state container ('struct max77620_chip'). devm_regmap_add_irq_chip() does not make a copy of 'struct regmap_irq_chip' but store the pointer.
Second probe - either successful or failure - would overwrite the 'irq_drv_data' from previous device probe, so interrupts would be executed in a wrong context.
--- drivers/mfd/max77620.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
drivers/mfd/max77620.c +11 -4
@@ -253,7 +253,7 @@ static int max77620_irq_global_unmask(voreturn ret; } -static struct regmap_irq_chip max77620_top_irq_chip = { +static const struct regmap_irq_chip max77620_top_irq_chip = { .name ="max77620-top" , .irqs = max77620_top_irqs, .num_irqs =ARRAY_SIZE (max77620_top_irqs),
@@ -498,6 +498,7 @@ static int max77620_probe(struct i2c_cliconst struct i2c_device_id *id =i2c_client_get_device_id (client);const struct regmap_config *rmap_config;struct max77620_chip *chip; +struct regmap_irq_chip *chip_desc;const struct mfd_cell *mfd_cells;int n_mfd_cells;bool pm_off;
@@ -508,6 +509,14 @@ static int max77620_probe(struct i2c_clireturn -ENOMEM ;i2c_set_clientdata (client, chip); + + chip_desc =devm_kmemdup (&client->dev, &max77620_top_irq_chip, +sizeof (max77620_top_irq_chip), +GFP_KERNEL ); +if (!chip_desc) +return -ENOMEM ; + chip_desc->irq_drv_data = chip; + chip->dev = &client->dev; chip->chip_irq = client->irq; chip->chip_id = (enum max77620_chip_id )id->driver_data;
@@ -544,11 +553,9 @@ static int max77620_probe(struct i2c_cliif (ret <0 )return ret; - max77620_top_irq_chip.irq_drv_data = chip; ret =devm_regmap_add_irq_chip (chip->dev, chip->rmap, client->irq,IRQF_ONESHOT |IRQF_SHARED ,0 , - &max77620_top_irq_chip, - &chip->top_irq_data); + chip_desc, &chip->top_irq_data);if (ret <0 ) {dev_err (chip->dev,"Failed to add regmap irq: %d\n" , ret);return ret;
Greg Kroah-Hartman
maintainerPATCH 572/737 media: rc: st_rc: Fix reset control resource leak
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haotian Zhang <[email protected]>
commit 1240abf4b71f632f0117b056e22488e4d9808938 upstream.
The driver calls reset_control_get_optional_exclusive() but never calls reset_control_put() in error paths or in the remove function. This causes a resource leak when probe fails after successfully acquiring the reset control, or when the driver is unloaded.
Switch to devm_reset_control_get_optional_exclusive() to automatically manage the reset control resource.
--- drivers/media/rc/st_rc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/rc/st_rc.c +1 -1
@@ -283,7 +283,7 @@ static int st_rc_probe(struct platform_delse rc_dev->rx_base = rc_dev->base; - rc_dev->rstc =reset_control_get_optional_exclusive (dev,NULL ); + rc_dev->rstc =devm_reset_control_get_optional_exclusive (dev,NULL );if (IS_ERR (rc_dev->rstc)) { ret =PTR_ERR (rc_dev->rstc); goto err;
Greg Kroah-Hartman
maintainerPATCH 573/737 parisc: entry.S: fix space adjustment on interruption for 64-bit userspace
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Schnelle <[email protected]>
commit 1aa4524c0c1b54842c4c0a370171d11b12d0709b upstream.
In wide mode, the IASQ contain the upper part of the GVA during interruption. This needs to be reversed before the space is used - otherwise it contains parts of IAOQ. See Page 2-13 "Processing Resources / Interruption Instruction Address Queues" in the Parisc 2.0 Architecture Manual page 2-13 for an explanation.
The IAOQ/IASQ space_adjust was skipped for other interruptions than itlb misses. However, the code in handle_interruption() checks whether iasq[0] contains a valid space. Due to the not masked out bits this match failed and the process was killed.
Also add space_adjust for IAOQ1/IASQ1 so ptregs contains sane values.
--- arch/parisc/kernel/entry.S | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
arch/parisc/kernel/entry.S +8 -3
@@ -1059,8 +1059,6 @@ ENTRY_CFI(intr_save) /* for os_hpmc */ STREG %r17, PT_IOR(%r29) #if defined(CONFIG_64BIT) - b,n intr_save2 - skip_save_ior: /* We have a itlb miss, and when executing code above 4 Gb on ILP64, we * need to adjust iasq/iaoq here in the same way we adjusted isr/ior
@@ -1069,10 +1067,17 @@ skip_save_ior: bb,COND(>=),n %r8,PSW_W_BIT,intr_save2 LDREG PT_IASQ0(%r29), %r16 LDREG PT_IAOQ0(%r29), %r17 - /* adjust iasq/iaoq */ + /* adjust iasq0/iaoq0 */ space_adjust %r16,%r17,%r1 STREG %r16, PT_IASQ0(%r29) STREG %r17, PT_IAOQ0(%r29) + + LDREG PT_IASQ1(%r29), %r16 + LDREG PT_IAOQ1(%r29), %r17 + /* adjust iasq1/iaoq1 */ + space_adjust %r16,%r17,%r1 + STREG %r16, PT_IASQ1(%r29) + STREG %r17, PT_IAOQ1(%r29) #else skip_save_ior: #endif
Greg Kroah-Hartman
maintainerPATCH 574/737 parisc: entry: set W bit for !compat tasks in syscall_restore_rfi()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Schnelle <[email protected]>
commit 5fb1d3ce3e74a4530042795e1e065422295f1371 upstream.
When the kernel leaves to userspace via syscall_restore_rfi(), the W bit is not set in the new PSW. This doesn't cause any problems because there's no 64 bit userspace for parisc. Simple static binaries are usually loaded at addresses way below the 32 bit limit so the W bit doesn't matter.
Fix this by setting the W bit when TIF_32BIT is not set.
--- arch/parisc/kernel/asm-offsets.c | 2 ++ arch/parisc/kernel/entry.S | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-)
arch/parisc/kernel/asm-offsets.c +2 -0
@@ -258,6 +258,8 @@ int main(void)BLANK ();DEFINE (TIF_BLOCKSTEP_PA_BIT ,31 -TIF_BLOCKSTEP );DEFINE (TIF_SINGLESTEP_PA_BIT ,31 -TIF_SINGLESTEP ); +DEFINE (TIF_32BIT_PA_BIT ,31 -TIF_32BIT ); +BLANK ();DEFINE (ASM_PMD_SHIFT ,PMD_SHIFT );DEFINE (ASM_PGDIR_SHIFT ,PGDIR_SHIFT );
arch/parisc/kernel/entry.S +4 -1
@@ -1846,6 +1846,10 @@ syscall_restore_rfi: extru,= %r19,TIF_BLOCKSTEP_PA_BIT,1,%r0 depi -1,7,1,%r20 /* T bit */ +#ifdef CONFIG_64BIT + extru,<> %r19,TIF_32BIT_PA_BIT,1,%r0 + depi -1,4,1,%r20 /* W bit */ +#endif STREG %r20,TASK_PT_PSW(%r1) /* Always store space registers, since sr3 can be changed (e.g. fork) */
@@ -1859,7 +1863,6 @@ syscall_restore_rfi: STREG %r25,TASK_PT_IASQ0(%r1) STREG %r25,TASK_PT_IASQ1(%r1) - /* XXX W bit??? */ /* Now if old D bit is clear, it means we didn't save all registers * on syscall entry, so do that now. This only happens on TRACEME * calls, or if someone attached to us while we were on a syscall.
Greg Kroah-Hartman
maintainerPATCH 575/737 powerpc/pseries/cmm: call balloon_devinfo_init() also without CONFIG_BALLOON_COMPACTION
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Hildenbrand <[email protected]>
commit fc6bcf9ac4de76f5e7bcd020b3c0a86faff3f2d5 upstream.
Patch series "powerpc/pseries/cmm: two smaller fixes".
Two smaller fixes identified while doing a bigger rework.
This patch (of 2):
We always have to initialize the balloon_dev_info, even when compaction is not configured in: otherwise the containing list and the lock are left uninitialized.
Likely not many such configs exist in practice, but let's CC stable to be sure.
This was found by code inspection.
--- arch/powerpc/platforms/pseries/cmm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/platforms/pseries/cmm.c +1 -1
@@ -550,7 +550,6 @@ static int cmm_migratepage(struct balloostatic void cmm_balloon_compaction_init (void ) { -balloon_devinfo_init (&b_dev_info); b_dev_info.migratepage = cmm_migratepage; }#else /* CONFIG_BALLOON_COMPACTION */
@@ -572,6 +571,7 @@ static int cmm_init(void)if (!firmware_has_feature (FW_FEATURE_CMO ) && !simulate)return -EOPNOTSUPP ; +balloon_devinfo_init (&b_dev_info);cmm_balloon_compaction_init (); rc =register_oom_notifier (&cmm_oom_nb);
Greg Kroah-Hartman
maintainerPATCH 576/737 media: adv7842: Avoid possible out-of-bounds array accesses in adv7842_cp_log_status()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ivan Abramov <[email protected]>
commit 8163419e3e05d71dcfa8fb49c8fdf8d76908fe51 upstream.
It's possible for cp_read() and hdmi_read() to return -EIO. Those values are further used as indexes for accessing arrays.
Fix that by checking return values where it's needed.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- drivers/media/i2c/adv7842.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/media/i2c/adv7842.c +5 -2
@@ -2680,6 +2680,7 @@ static int adv7842_cp_log_status(struct/* CP block */ struct adv7842_state *state =to_state (sd);struct v4l2_dv_timings timings; +int temp;u8 reg_io_0x02 =io_read (sd,0x02 );u8 reg_io_0x21 =io_read (sd,0x21 );u8 reg_rep_0x77 =rep_read (sd,0x77 );
@@ -2802,8 +2803,9 @@ static int adv7842_cp_log_status(struct (((reg_io_0x02 >>2 ) &0x01 ) ^ (reg_io_0x02 &0x01 )) ?"(16-235)" :"(0-255)" , (reg_io_0x02 & 0x08) ? "enabled" : "disabled"); + temp =cp_read (sd,0xf4 ) >>4 ;v4l2_info (sd,"Color space conversion: %s\n" , - csc_coeff_sel_rb[cp_read (sd,0xf4 ) >>4 ]); + temp <0 ?"" : csc_coeff_sel_rb[temp]);if (!is_digital_input (sd))return 0 ;
@@ -2833,8 +2835,9 @@ static int adv7842_cp_log_status(struct hdmi_read(sd, 0x5f));v4l2_info (sd,"AV Mute: %s\n" , (hdmi_read (sd,0x04 ) &0x40 ) ?"on" :"off" ); + temp =hdmi_read (sd,0x0b ) >>6 ;v4l2_info (sd,"Deep color mode: %s\n" , - deep_color_mode_txt[hdmi_read (sd,0x0b ) >>6 ]); + temp <0 ?"" : deep_color_mode_txt[temp]);adv7842_log_infoframes (sd);
Greg Kroah-Hartman
maintainerPATCH 577/737 firmware: stratix10-svc: Add mutex in stratix10 memory management
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mahesh Rao <[email protected]>
commit 85f96cbbbc67b59652b2c1ec394b8ddc0ddf1b0b upstream.
Add mutex lock to stratix10_svc_allocate_memory and stratix10_svc_free_memory for thread safety. This prevents race conditions and ensures proper synchronization during memory operations. This is required for parallel communication with the Stratix10 service channel.
--- drivers/firmware/stratix10-svc.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
drivers/firmware/stratix10-svc.c +11 -0
@@ -1,6 +1,7 @@// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2017-2018, Intel Corporation +* Copyright (C) 2025, Altera Corporation */ #include <linux/completion.h>
@@ -176,6 +177,12 @@ static LIST_HEAD(svc_ctrl);static LIST_HEAD (svc_data_mem);/** +* svc_mem_lock protects access to the svc_data_mem list for +* concurrent multi-client operations +*/ +static DEFINE_MUTEX (svc_mem_lock); + +/** * svc_pa_to_va() - translate physical address to virtual address * @addr: to be translated physical address *
@@ -187,6 +194,7 @@ static void *svc_pa_to_va(unsigned longstruct stratix10_svc_data_mem *pmem;pr_debug ("claim back P-addr=0x%016x\n" , (unsigned int )addr); +guard (mutex)(&svc_mem_lock);list_for_each_entry (pmem, &svc_data_mem, node)if (pmem->paddr == addr)return pmem->vaddr;
@@ -996,6 +1004,7 @@ int stratix10_svc_send(struct stratix10_ p_data->flag = ct->flags; } }else { +guard (mutex)(&svc_mem_lock);list_for_each_entry (p_mem, &svc_data_mem, node)if (p_mem->vaddr == p_msg->payload) { p_data->paddr = p_mem->paddr;
@@ -1078,6 +1087,7 @@ void *stratix10_svc_allocate_memory(struif (!pmem)return ERR_PTR (-ENOMEM ); +guard (mutex)(&svc_mem_lock); va =gen_pool_alloc (genpool, s);if (!va)return ERR_PTR (-ENOMEM );
@@ -1106,6 +1116,7 @@ EXPORT_SYMBOL_GPL(stratix10_svc_allocatevoid stratix10_svc_free_memory (struct stratix10_svc_chan *chan,void *kaddr) {struct stratix10_svc_data_mem *pmem; +guard (mutex)(&svc_mem_lock);list_for_each_entry (pmem, &svc_data_mem, node)if (pmem->vaddr == kaddr) {
Greg Kroah-Hartman
maintainerPATCH 578/737 dm-ebs: Mark full buffer dirty even on partial write
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uladzislau Rezki (Sony) <[email protected]>
commit 7fa3e7d114abc9cc71cc35d768e116641074ddb4 upstream.
When performing a read-modify-write(RMW) operation, any modification to a buffered block must cause the entire buffer to be marked dirty.
Marking only a subrange as dirty is incorrect because the underlying device block size(ubs) defines the minimum read/write granularity. A lower device can perform I/O only on regions which are fully aligned and sized to ubs.
This change ensures that write-back operations always occur in full ubs-sized chunks, matching the intended emulation semantics of the EBS target.
As for user space visible impact, submitting sub-ubs and misaligned I/O for devices which are tuned to ubs sizes only, will reject such requests, therefore it can lead to losing data. Example:
1) Create a 8K nvme device in qemu by adding
-device nvme,drive=drv0,serial=foo,logical_block_size=8192,physical_block_size=8192
2) Setup dm-ebs to emulate 512B to 8K mapping
urezki@pc638:~/bin$ cat dmsetup.sh
lower=/dev/nvme0n1
len=$(blockdev --getsz "$lower")
echo "0 $len ebs $lower 0 1 16" | dmsetup create nvme-8k urezki@pc638:~/bin$
offset 0, ebs=1 and ubs=16(in sectors).
3) Create an ext4 filesystem(default 4K block size)
urezki@pc638:~/bin$ sudo mkfs.ext4 -F /dev/dm-0
mke2fs 1.47.0 (5-Feb-2023)
Discarding device blocks: done
Creating filesystem with 2072576 4k blocks and 518144 inodes
Filesystem UUID: bd0b6ca6-0506-4e31-86da-8d22c9d50b63
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632Allocating group tables: done
Writing inode tables: done
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: mkfs.ext4: Input/output error while writing out and closing file system
urezki@pc638:~/bin$ dmesg
<snip>
[ 1618.875449] buffer_io_error: 1028 callbacks suppressed [ 1618.875456] Buffer I/O error on dev dm-0, logical block 0, lost async page write [ 1618.875527] Buffer I/O error on dev dm-0, logical block 1, lost async page write [ 1618.875602] Buffer I/O error on dev dm-0, logical block 2, lost async page write [ 1618.875620] Buffer I/O error on dev dm-0, logical block 3, lost async page write [ 1618.875639] Buffer I/O error on dev dm-0, logical block 4, lost async page write [ 1618.894316] Buffer I/O error on dev dm-0, logical block 5, lost async page write [ 1618.894358] Buffer I/O error on dev dm-0, logical block 6, lost async page write [ 1618.894380] Buffer I/O error on dev dm-0, logical block 7, lost async page write [ 1618.894405] Buffer I/O error on dev dm-0, logical block 8, lost async page write [ 1618.894427] Buffer I/O error on dev dm-0, logical block 9, lost async page write
<snip>
Many I/O errors because the lower 8K device rejects sub-ubs/misaligned requests.
with a patch:
urezki@pc638:~/bin$ sudo mkfs.ext4 -F /dev/dm-0
mke2fs 1.47.0 (5-Feb-2023)
Discarding device blocks: done
Creating filesystem with 2072576 4k blocks and 518144 inodes
Filesystem UUID: 9b54f44f-ef55-4bd4-9e40-c8b775a616ac
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632Allocating group tables: done
Writing inode tables: done
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done
urezki@pc638:~/bin$ sudo mount /dev/dm-0 /mnt/ urezki@pc638:~/bin$ ls -al /mnt/ total 24 drwxr-xr-x 3 root root 4096 Oct 17 15:13 . drwxr-xr-x 19 root root 4096 Jul 10 19:42 .. drwx------ 2 root root 16384 Oct 17 15:13 lost+found urezki@pc638:~/bin$
After this change: mkfs completes; mount succeeds.
--- drivers/md/dm-ebs-target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/md/dm-ebs-target.c +1 -1
@@ -103,7 +103,7 @@ static int __ebs_rw_bvec(struct ebs_c *e }else {flush_dcache_page (bv->bv_page);memcpy (ba, pa, cur_len); -dm_bufio_mark_partial_buffer_dirty (b, buf_off, buf_off + cur_len); +dm_bufio_mark_buffer_dirty (b); }dm_bufio_release (b);
Greg Kroah-Hartman
maintainerPATCH 579/737 dm-bufio: align write boundary on physical block size
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikulas Patocka <[email protected]>
commit d0ac06ae53be0cdb61f5fe6b62d25d3317c51657 upstream.
There may be devices with physical block size larger than 4k.
If dm-bufio sends I/O that is not aligned on physical block size, performance is degraded.
The 4k minimum alignment limit is there because some SSDs report logical and physical block size 512 despite having 4k internally - so dm-bufio shouldn't send I/Os not aligned on 4k boundary, because they perform badly (the SSD does read-modify-write for them).
--- drivers/md/dm-bufio.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/md/dm-bufio.c +6 -4
@@ -1375,7 +1375,7 @@ static void submit_io(struct dm_buffer * {unsigned int n_sectors;sector_t sector; -unsigned int offset, end; +unsigned int offset, end, align; b->end_io = end_io;
@@ -1389,9 +1389,11 @@ static void submit_io(struct dm_buffer * b->c->write_callback (b); offset = b->write_start; end = b->write_end; - offset &= -DM_BUFIO_WRITE_ALIGN ; - end +=DM_BUFIO_WRITE_ALIGN -1 ; - end &= -DM_BUFIO_WRITE_ALIGN ; + align =max (DM_BUFIO_WRITE_ALIGN , +bdev_physical_block_size (b->c->bdev)); + offset &= -align; + end += align -1 ; + end &= -align;if (unlikely (end > b->c->block_size)) end = b->c->block_size;
Greg Kroah-Hartman
maintainerPATCH 580/737 fbdev: gbefb: fix to use physical address instead of dma address
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rene Rebe <[email protected]>
commit e3f44742bbb10537fe53d83d20dea2a7c167674d upstream.
While debuggigng why X would not start on mips64 Sgi/O2 I found the phys adress being off. Turns out the gbefb passed the internal dma_addr as phys. May be broken pre git history. Fix by converting dma_to_phys.
--- drivers/video/fbdev/gbefb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/video/fbdev/gbefb.c +3 -2
@@ -12,6 +12,7 @@#include <linux/delay.h> #include <linux/platform_device.h> #include <linux/dma-mapping.h> +#include <linux/dma-direct.h> #include <linux/errno.h> #include <linux/gfp.h> #include <linux/fb.h>
@@ -65,7 +66,7 @@ struct gbefb_par {static unsigned int gbe_mem_size =CONFIG_FB_GBE_MEM *1024 *1024 ;static void *gbe_mem;static dma_addr_t gbe_dma_addr; -static unsigned long gbe_mem_phys; +static phys_addr_t gbe_mem_phys; static struct { uint16_t *cpu;
@@ -1182,7 +1183,7 @@ static int gbefb_probe(struct platform_d goto out_release_mem_region; } - gbe_mem_phys = (unsigned long ) gbe_dma_addr; + gbe_mem_phys =dma_to_phys (&p_dev->dev, gbe_dma_addr); } par = info->par;
Greg Kroah-Hartman
maintainerPATCH 581/737 fbdev: pxafb: Fix multiple clamped values in pxafb_adjust_timing
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum <[email protected]>
commit 0155e868cbc111846cc2809c1546ea53810a56ae upstream.
The variables were never clamped because the return value of clamp_val() was not used. Fix this by assigning the clamped values, and use clamp() instead of clamp_val().
--- drivers/video/fbdev/pxafb.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/video/fbdev/pxafb.c +6 -6
@@ -418,12 +418,12 @@ static int pxafb_adjust_timing(struct px var->yres =max_t (int, var->yres,MIN_YRES );if (!(fbi->lccr0 &LCCR0_LCDT )) { -clamp_val (var->hsync_len,1 ,64 ); -clamp_val (var->vsync_len,1 ,64 ); -clamp_val (var->left_margin,1 ,255 ); -clamp_val (var->right_margin,1 ,255 ); -clamp_val (var->upper_margin,1 ,255 ); -clamp_val (var->lower_margin,1 ,255 ); + var->hsync_len =clamp (var->hsync_len,1 ,64 ); + var->vsync_len =clamp (var->vsync_len,1 ,64 ); + var->left_margin =clamp (var->left_margin,1 ,255 ); + var->right_margin =clamp (var->right_margin,1 ,255 ); + var->upper_margin =clamp (var->upper_margin,1 ,255 ); + var->lower_margin =clamp (var->lower_margin,1 ,255 ); }/* make sure each line is aligned on word boundary */
Greg Kroah-Hartman
maintainerPATCH 582/737 fbdev: tcx.c fix mem_map to correct smem_start offset
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: René Rebe <[email protected]>
commit 35fa2b4bf96415b88d7edaa5cf8af5185d9ce76e upstream.
403ae52ac047 ("sparc: fix drivers/video/tcx.c warning") changed the physbase initializing breaking the user-space mmap, e.g. for Xorg entirely.
Fix fbdev mmap table so the sbus mmap helper work correctly, and not try to map vastly (physbase) offset memory.
--- drivers/video/fbdev/tcx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/video/fbdev/tcx.c +1 -1
@@ -436,7 +436,7 @@ static int tcx_probe(struct platform_dev j = i;break ; } - par->mmap_map[i].poff = op->resource[j].start; + par->mmap_map[i].poff = op->resource[j].start - info->fix.smem_start; } info->fbops = &tcx_ops;
Greg Kroah-Hartman
maintainerPATCH 583/737 media: cec: Fix debugfs leak on bus_register() failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haotian Zhang <[email protected]>
commit c43bcd2b2aa3c2ca9d2433c3990ecbc2c47d10eb upstream.
In cec_devnode_init(), the debugfs directory created with debugfs_create_dir() is not removed if bus_register() fails. This leaves a stale "cec" entry in debugfs and prevents proper module reloading.
Fix this by removing the debugfs directory in the error path.
--- drivers/media/cec/core/cec-core.c | 1 + 1 file changed, 1 insertion(+)
drivers/media/cec/core/cec-core.c +1 -0
@@ -449,6 +449,7 @@ static int __init cec_devnode_init(void) ret =bus_register (&cec_bus_type);if (ret <0 ) { +debugfs_remove_recursive (top_cec_dir);unregister_chrdev_region (cec_dev_t,CEC_NUM_DEVICES );pr_warn ("cec: bus_register failed\n" );return -EIO ;
Greg Kroah-Hartman
maintainerPATCH 584/737 media: msp3400: Avoid possible out-of-bounds array accesses in msp3400c_thread()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ivan Abramov <[email protected]>
commit d2bceb2e20e783d57e739c71e4e50b4b9f4a3953 upstream.
It's possible for max1 to remain -1 if msp_read() always fail. This variable is further used as index for accessing arrays.
Fix that by checking max1 prior to array accesses.
It seems that restart is the preferable action in case of out-of-bounds value.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- drivers/media/i2c/msp3400-kthreads.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/media/i2c/msp3400-kthreads.c +2 -0
@@ -596,6 +596,8 @@ restart: "carrier2 val: %5d / %s\n", val, cd[i].name); } +if (max1 <0 || max1 >3 ) + goto restart;/* program the msp3400 according to the results */ state->main = msp3400c_carrier_detect_main[max1].cdo;switch (max1) {
Greg Kroah-Hartman
maintainerPATCH 585/737 media: renesas: rcar_drif: fix device node reference leak in rcar_drif_bond_enabled
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miaoqian Lin <[email protected]>
commit 445e1658894fd74eab7e53071fa16233887574ed upstream.
The function calls of_parse_phandle() which returns
a device node with an incremented reference count. When the bonded device is not available, the function
returns NULL without releasing the reference, causing a reference leak.
Add of_node_put(np) to release the device node reference. The of_node_put function handles NULL pointers.
Found through static analysis by reviewing the doc of of_parse_phandle() and cross-checking its usage patterns across the codebase.
--- drivers/media/platform/renesas/rcar_drif.c | 1 + 1 file changed, 1 insertion(+)
drivers/media/platform/renesas/rcar_drif.c +1 -0
@@ -1249,6 +1249,7 @@ static struct device_node *rcar_drif_bonif (np &&of_device_is_available (np))return np; +of_node_put (np);return NULL ; }
Greg Kroah-Hartman
maintainerPATCH 586/737 media: samsung: exynos4-is: fix potential ABBA deadlock on init
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marek Szyprowski <[email protected]>
commit 17dc8ccd6dd5ffe30aa9b0d36e2af1389344ce2b upstream.
v4l2_device_register_subdev_nodes() must called without taking media_dev->graph_mutex to avoid potential AB-BA deadlock on further subdevice driver initialization.
--- drivers/media/platform/samsung/exynos4-is/media-dev.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/media/platform/samsung/exynos4-is/media-dev.c +6 -4
@@ -1410,12 +1410,14 @@ static int subdev_notifier_complete(strumutex_lock (&fmd->media_dev.graph_mutex); ret =fimc_md_create_links (fmd); -if (ret <0 ) - goto unlock; +if (ret <0 ) { +mutex_unlock (&fmd->media_dev.graph_mutex); +return ret; + } - ret =v4l2_device_register_subdev_nodes (&fmd->v4l2_dev); -unlock:mutex_unlock (&fmd->media_dev.graph_mutex); + + ret =v4l2_device_register_subdev_nodes (&fmd->v4l2_dev);if (ret <0 )return ret;
Greg Kroah-Hartman
maintainerPATCH 587/737 media: TDA1997x: Remove redundant cancel_delayed_work in probe
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Duoming Zhou <[email protected]>
commit 29de195ca39fc2ac0af6fd45522994df9f431f80 upstream.
The delayed_work delayed_work_enable_hpd is initialized with INIT_DELAYED_WORK(), but it is never scheduled in tda1997x_probe().
Calling cancel_delayed_work() on a work that has never been scheduled is redundant and unnecessary, as there is no pending work to cancel.
Remove the redundant cancel_delayed_work() from error handling path in tda1997x_probe() to avoid potential confusion.
--- drivers/media/i2c/tda1997x.c | 1 - 1 file changed, 1 deletion(-)
drivers/media/i2c/tda1997x.c +0 -1
@@ -2794,7 +2794,6 @@ err_free_media: err_free_handler:v4l2_ctrl_handler_free (&state->hdl); err_free_mutex: -cancel_delayed_work (&state->delayed_work_enable_hpd);mutex_destroy (&state->page_lock);mutex_destroy (&state->lock);tda1997x_set_power (state,0 );
Greg Kroah-Hartman
maintainerPATCH 588/737 media: verisilicon: Protect G2 HEVC decoder against invalid DPB index
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolas Dufresne <[email protected]>
commit 47825b1646a6a9eca0f90baa3d4f98947c2add96 upstream.
Fix the Hantro G2 HEVC decoder so that we use DPB index 0 whenever a ninvalid index is received from user space. This protects the hardware from doing faulty memory access which then leads to bus errors.
To be noted that when a reference is missing, userspace such as GStreamer passes an invalid DPB index of 255. This issue was found by seeking to a CRA picture using GStreamer. The framework is currently missing the code to skip over RASL pictures placed after the CRA. This situation can also occur while doing live streaming over lossy transport.
--- drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c +13 -2
@@ -297,6 +297,15 @@ static void set_params(struct hantro_ctxhantro_reg_write (vpu, &g2_apf_threshold,8 ); } +static u32 get_dpb_index (const struct v4l2_ctrl_hevc_decode_params *decode_params, +const u32 index) +{ +if (index > decode_params->num_active_dpb_entries) +return 0 ; + +return index; +} +static void set_ref_pic_list (struct hantro_ctx *ctx) {const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls;
@@ -369,8 +378,10 @@ static void set_ref_pic_list(struct hant list1[j++] = list1[i++];for (i =0 ; i <V4L2_HEVC_DPB_ENTRIES_NUM_MAX ; i++) { -hantro_reg_write (vpu, &ref_pic_regs0[i], list0[i]); -hantro_reg_write (vpu, &ref_pic_regs1[i], list1[i]); +hantro_reg_write (vpu, &ref_pic_regs0[i], +get_dpb_index (decode_params, list0[i])); +hantro_reg_write (vpu, &ref_pic_regs1[i], +get_dpb_index (decode_params, list1[i])); } }
Greg Kroah-Hartman
maintainerPATCH 589/737 media: videobuf2: Fix device reference leak in vb2_dc_alloc error path
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haotian Zhang <[email protected]>
commit 94de23a9aa487d7c1372efb161721d7949a177ae upstream.
In vb2_dc_alloc(), get_device() is called to increment the device reference count. However, if subsequent DMA allocation fails (vb2_dc_alloc_coherent or vb2_dc_alloc_non_coherent returns error), the function returns without calling put_device(), causing a device reference leak.
Add put_device() call in the error path before kfree() to properly release the device reference acquired earlier.
--- drivers/media/common/videobuf2/videobuf2-dma-contig.c | 1 + 1 file changed, 1 insertion(+)
drivers/media/common/videobuf2/videobuf2-dma-contig.c +1 -0
@@ -258,6 +258,7 @@ static void *vb2_dc_alloc(struct vb2_bufif (ret) {dev_err (dev,"dma alloc of size %lu failed\n" , size); +put_device (buf->dev);kfree (buf);return ERR_PTR (-ENOMEM ); }
Greg Kroah-Hartman
maintainerPATCH 590/737 media: vpif_capture: fix section mismatch
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 0ef841113724166c3c484d0e9ae6db1eb5634fde upstream.
Platform drivers can be probed after their init sections have been discarded (e.g. on probe deferral or manual rebind through sysfs) so the probe function must not live in init.
Note that commit ffa1b391c61b ("V4L/DVB: vpif_cap/disp: Removed section mismatch warning") incorrectly suppressed the modpost warning.
--- drivers/media/platform/ti/davinci/vpif_capture.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/media/platform/ti/davinci/vpif_capture.c +2 -2
@@ -1601,7 +1601,7 @@ err_cleanup:* This creates device entries by register itself to the V4L2 driver and * initializes fields of each channel objects */ -static __init int vpif_probe (struct platform_device *pdev) +static int vpif_probe (struct platform_device *pdev) {struct vpif_subdev_info *subdevdata;struct i2c_adapter *i2c_adap;
@@ -1808,7 +1808,7 @@ static int vpif_resume(struct device *de static SIMPLE_DEV_PM_OPS(vpif_pm_ops, vpif_suspend, vpif_resume); -static __refdata struct platform_driver vpif_driver = { +static struct platform_driver vpif_driver = { .driver = { .name =VPIF_DRIVER_NAME , .pm = &vpif_pm_ops,
Greg Kroah-Hartman
maintainerPATCH 591/737 media: vpif_display: fix section mismatch
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 59ca64bf98e4209df8ace8057d31ae3c80f948cd upstream.
Platform drivers can be probed after their init sections have been discarded (e.g. on probe deferral or manual rebind through sysfs) so the probe function must not live in init.
Note that commit ffa1b391c61b ("V4L/DVB: vpif_cap/disp: Removed section mismatch warning") incorrectly suppressed the modpost warning.
--- drivers/media/platform/ti/davinci/vpif_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/media/platform/ti/davinci/vpif_display.c +2 -2
@@ -1215,7 +1215,7 @@ probe_out:* vpif_probe: This function creates device entries by register itself to the * V4L2 driver and initializes fields of each channel objects */ -static __init int vpif_probe (struct platform_device *pdev) +static int vpif_probe (struct platform_device *pdev) {struct vpif_subdev_info *subdevdata;struct i2c_adapter *i2c_adap;
@@ -1391,7 +1391,7 @@ static int vpif_resume(struct device *de static SIMPLE_DEV_PM_OPS(vpif_pm_ops, vpif_suspend, vpif_resume); -static __refdata struct platform_driver vpif_driver = { +static struct platform_driver vpif_driver = { .driver = { .name =VPIF_DRIVER_NAME , .pm = &vpif_pm_ops,
Greg Kroah-Hartman
maintainerPATCH 592/737 media: amphion: Cancel message work before releasing the VPU core
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Qian <[email protected]>
commit ae246b0032146e352c4c06a7bf03cd3d5bcb2ecd upstream.
To avoid accessing the VPU register after release of the VPU core, cancel the message work and destroy the workqueue that handles the VPU message before release of the VPU core.
--- drivers/media/platform/amphion/vpu_v4l2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/media/platform/amphion/vpu_v4l2.c +3 -3
@@ -682,15 +682,15 @@ static int vpu_v4l2_release(struct vpu_i {vpu_trace (inst->vpu->dev,"%p\n" , inst); -vpu_release_core (inst->core); -put_device (inst->dev); -if (inst->workqueue) {cancel_work_sync (&inst->msg_work);destroy_workqueue (inst->workqueue); inst->workqueue =NULL ; } +vpu_release_core (inst->core); +put_device (inst->dev); +v4l2_ctrl_handler_free (&inst->ctrl_handler);mutex_destroy (&inst->lock);
Greg Kroah-Hartman
maintainerPATCH 593/737 media: i2c: ADV7604: Remove redundant cancel_delayed_work in probe
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Duoming Zhou <[email protected]>
commit 8f34f24355a607b98ecd9924837aab13c676eeca upstream.
The delayed_work delayed_work_enable_hotplug is initialized with INIT_DELAYED_WORK() in adv76xx_probe(), but it is never scheduled anywhere in the probe function.
Calling cancel_delayed_work() on a work that has never been scheduled is redundant and unnecessary, as there is no pending work to cancel.
Remove the redundant cancel_delayed_work() from error handling path and adjust the goto label accordingly to simplify the code and avoid potential confusion.
--- drivers/media/i2c/adv7604.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
drivers/media/i2c/adv7604.c +1 -3
@@ -3620,7 +3620,7 @@ static int adv76xx_probe(struct i2c_clie err =media_entity_pads_init (&sd->entity, state->source_pad +1 , state->pads);if (err) - goto err_work_queues; + goto err_i2c;/* Configure regmaps */ err =configure_regmaps (state);
@@ -3661,8 +3661,6 @@ static int adv76xx_probe(struct i2c_clie err_entity:media_entity_cleanup (&sd->entity); -err_work_queues: -cancel_delayed_work (&state->delayed_work_enable_hotplug); err_i2c:adv76xx_unregister_clients (state); err_hdl:
Greg Kroah-Hartman
maintainerPATCH 594/737 media: i2c: adv7842: Remove redundant cancel_delayed_work in probe
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Duoming Zhou <[email protected]>
commit e66a5cc606c58e72f18f9cdd868a3672e918f9f8 upstream.
The delayed_work delayed_work_enable_hotplug is initialized with INIT_DELAYED_WORK() in adv7842_probe(), but it is never scheduled anywhere in the probe function.
Calling cancel_delayed_work() on a work that has never been scheduled is redundant and unnecessary, as there is no pending work to cancel.
Remove the redundant cancel_delayed_work() from error handling path and adjust the goto label accordingly to simplify the code and avoid potential confusion.
--- drivers/media/i2c/adv7842.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
drivers/media/i2c/adv7842.c +1 -3
@@ -3564,7 +3564,7 @@ static int adv7842_probe(struct i2c_clie err =media_entity_pads_init (&sd->entity,ADV7842_PAD_SOURCE +1 , state->pads);if (err) - goto err_work_queues; + goto err_i2c; err =adv7842_core_init (sd);if (err)
@@ -3585,8 +3585,6 @@ static int adv7842_probe(struct i2c_clie err_entity:media_entity_cleanup (&sd->entity); -err_work_queues: -cancel_delayed_work (&state->delayed_work_enable_hotplug); err_i2c:adv7842_unregister_clients (sd); err_hdl:
Greg Kroah-Hartman
maintainerPATCH 595/737 media: mediatek: vcodec: Fix a reference leak in mtk_vcodec_fw_vpu_init()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haoxiang Li <[email protected]>
commit cdd0f118ef87db8a664fb5ea366fd1766d2df1cd upstream.
vpu_get_plat_device() increases the reference count of the returned platform device. However, when devm_kzalloc() fails, the reference is not released, causing a reference leak.
Fix this by calling put_device() on fw_pdev->dev before returning on the error path.
--- drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vpu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vpu.c +3 -1
@@ -117,8 +117,10 @@ struct mtk_vcodec_fw *mtk_vcodec_fw_vpu_vpu_wdt_reg_handler (fw_pdev, mtk_vcodec_vpu_reset_enc_handler, priv, rst_id); fw =devm_kzalloc (&plat_dev->dev,sizeof (*fw),GFP_KERNEL ); -if (!fw) +if (!fw) { +put_device (&fw_pdev->dev);return ERR_PTR (-ENOMEM ); + } fw->type =VPU ; fw->ops = &mtk_vcodec_vpu_msg; fw->pdev = fw_pdev;
Greg Kroah-Hartman
maintainerPATCH 596/737 LoongArch: Add new PCI ID for pci_fixup_vgadev()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Huacai Chen <[email protected]>
commit bf3fa8f232a1eec8d7b88dcd9e925e60f04f018d upstream.
Loongson-2K3000 has a new PCI ID (0x7a46) for its display controller, Add it for pci_fixup_vgadev() since we prefer a discrete graphics card as default boot device if present.
--- arch/loongarch/pci/pci.c | 2 ++ 1 file changed, 2 insertions(+)
arch/loongarch/pci/pci.c +2 -0
@@ -15,6 +15,7 @@#define PCI_DEVICE_ID_LOONGSON_HOST 0x7a00#define PCI_DEVICE_ID_LOONGSON_DC1 0x7a06#define PCI_DEVICE_ID_LOONGSON_DC2 0x7a36 +#define PCI_DEVICE_ID_LOONGSON_DC3 0x7a46int raw_pci_read (unsigned int domain,unsigned int bus,unsigned int devfn,int reg,int len,u32 *val)
@@ -98,3 +99,4 @@ static void pci_fixup_vgadev(struct pci_ }DECLARE_PCI_FIXUP_FINAL (PCI_VENDOR_ID_LOONGSON ,PCI_DEVICE_ID_LOONGSON_DC1 , pci_fixup_vgadev);DECLARE_PCI_FIXUP_FINAL (PCI_VENDOR_ID_LOONGSON ,PCI_DEVICE_ID_LOONGSON_DC2 , pci_fixup_vgadev); +DECLARE_PCI_FIXUP_FINAL (PCI_VENDOR_ID_LOONGSON ,PCI_DEVICE_ID_LOONGSON_DC3 , pci_fixup_vgadev);
Greg Kroah-Hartman
maintainerPATCH 597/737 LoongArch: Correct the calculation logic of thread_count
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qiang Ma <[email protected]>
commit 1de0ae21f136efa6c5d8a4d3e07b7d1ca39c750f upstream.
For thread_count, the current calculation method has a maximum of 255, which may not be sufficient in the future. Therefore, we are correcting it now.
Reference: SMBIOS Specification, 7.5 Processor Information (Type 4)[1]
[1]: https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.9.0.pdf
--- arch/loongarch/kernel/setup.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
arch/loongarch/kernel/setup.c +7 -1
@@ -56,6 +56,7 @@#define SMBIOS_FREQLOW_MASK 0xFF#define SMBIOS_CORE_PACKAGE_OFFSET 0x23#define SMBIOS_THREAD_PACKAGE_OFFSET 0x25 +#define SMBIOS_THREAD_PACKAGE_2_OFFSET 0x2E#define LOONGSON_EFI_ENABLE (1 << 3)#ifdef CONFIG_EFI
@@ -130,7 +131,12 @@ static void __init parse_cpu_table(const cpu_clock_freq = freq_temp *1000000 ; loongson_sysconf.cpuname = (void *)dmi_string_parse (dm, dmi_data[16 ]); - loongson_sysconf.cores_per_package = *(dmi_data +SMBIOS_THREAD_PACKAGE_OFFSET ); + loongson_sysconf.cores_per_package = *(u8 *)(dmi_data +SMBIOS_THREAD_PACKAGE_OFFSET ); +if (dm->length >=0x30 && loongson_sysconf.cores_per_package ==0xff ) { +/* SMBIOS 3.0+ has ThreadCount2 for more than 255 threads */ + loongson_sysconf.cores_per_package = + *(u16 *)(dmi_data +SMBIOS_THREAD_PACKAGE_2_OFFSET ); + }pr_info ("CpuClock = %llu\n" , cpu_clock_freq); }
Greg Kroah-Hartman
maintainerPATCH 598/737 LoongArch: Fix build errors for CONFIG_RANDSTRUCT
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Huacai Chen <[email protected]>
commit 3c250aecef62da81deb38ac6738ac0a88d91f1fc upstream.
When CONFIG_RANDSTRUCT enabled, members of task_struct are randomized. There is a chance that TASK_STACK_CANARY be out of 12bit immediate's range and causes build errors. TASK_STACK_CANARY is naturally aligned, so fix it by replacing ld.d/st.d with ldptr.d/stptr.d which have 14bit immediates.
--- arch/loongarch/kernel/switch.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/loongarch/kernel/switch.S +2 -2
@@ -25,8 +25,8 @@ SYM_FUNC_START(__switch_to) stptr.d a4, a0, THREAD_SCHED_CFA #if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_SMP) la t7, __stack_chk_guard - LONG_L t8, a1, TASK_STACK_CANARY - LONG_S t8, t7, 0 + ldptr.d t8, a1, TASK_STACK_CANARY + stptr.d t8, t7, 0 #endif move tp, a2 cpu_restore_nonscratch a1
Greg Kroah-Hartman
maintainerPATCH 599/737 LoongArch: Use __pmd()/__pte() for swap entry conversions
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: WangYuli <[email protected]>
commit 4a71df151e703b5e7e85b33369cee59ef2665e61 upstream.
The __pmd() and __pte() helper macros provide the correct initialization syntax and abstraction for the pmd_t and pte_t types.
Use __pmd() to fix follow warning about __swp_entry_to_pmd() with gcc-15 under specific configs [1] :
In file included from ./include/linux/pgtable.h:6,
from ./include/linux/mm.h:31,
from ./include/linux/pagemap.h:8,
from arch/loongarch/mm/init.c:14:
./include/linux/swapops.h: In function ‘swp_entry_to_pmd’:
./arch/loongarch/include/asm/pgtable.h:302:34: error: missing braces around initializer [-Werror=missing-braces]
302 | #define __swp_entry_to_pmd(x) ((pmd_t) { (x).val | _PAGE_HUGE })
| ^
./include/linux/swapops.h:559:16: note: in expansion of macro ‘__swp_entry_to_pmd’
559 | return __swp_entry_to_pmd(arch_entry);
| ^~~~~~~~~~~~~~~~~~cc1: all warnings being treated as errors
Also update __swp_entry_to_pte() to use __pte() for consistency.
[1]. https://download.01.org/0day-ci/archive/20251119/[email protected]/config
--- arch/loongarch/include/asm/pgtable.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/loongarch/include/asm/pgtable.h +2 -2
@@ -285,9 +285,9 @@ static inline pte_t mk_swap_pte(unsigned#define __swp_offset (x) ((x).val >> 24)#define __swp_entry (type, offset) ((swp_entry_t) { pte_val(mk_swap_pte((type), (offset))) })#define __pte_to_swp_entry (pte) ((swp_entry_t) { pte_val(pte) }) -#define __swp_entry_to_pte (x) ((pte_t) { (x).val }) +#define __swp_entry_to_pte (x) __pte((x).val)#define __pmd_to_swp_entry (pmd) ((swp_entry_t) { pmd_val(pmd) }) -#define __swp_entry_to_pmd (x) ((pmd_t) { (x).val | _PAGE_HUGE }) +#define __swp_entry_to_pmd (x) __pmd((x).val | _PAGE_HUGE)static inline int pte_swp_exclusive (pte_t pte) {
Greg Kroah-Hartman
maintainerPATCH 600/737 LoongArch: Use unsigned long for _end and _text
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tiezhu Yang <[email protected]>
commit a258a3cb1895e3acf5f2fe245d17426e894bc935 upstream.
It is better to use unsigned long rather than long for _end and _text to calculate the kernel length.
--- arch/loongarch/kernel/relocate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/loongarch/kernel/relocate.c +2 -2
@@ -141,7 +141,7 @@ static inline void __init *determine_relif (kaslr_disabled ())return destination; - kernel_length = (long )_end - (long )_text; + kernel_length = (unsigned long )_end - (unsigned long )_text; random_offset =get_random_boot () <<16 ; random_offset &= (CONFIG_RANDOMIZE_BASE_MAX_OFFSET -1 );
@@ -190,7 +190,7 @@ unsigned long __init relocate_kernel(voiearly_memunmap (cmdline,COMMAND_LINE_SIZE );if (random_offset) { - kernel_length = (long )(_end) - (long )(_text); + kernel_length = (unsigned long )(_end) - (unsigned long )(_text);/* Copy the kernel to it's new location */ memcpy (location_new, _text, kernel_length);
Greg Kroah-Hartman
maintainerPATCH 601/737 compiler_types.h: add "auto" as a macro for "__auto_type"
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: H. Peter Anvin <[email protected]>
commit 2fb6915fa22dc5524d704afba58a13305dd9f533 upstream.
"auto" was defined as a keyword back in the K&R days, but as a storage type specifier. No one ever used it, since it was and is the default storage type for local variables.
C++11 recycled the keyword to allow a type to be declared based on the type of an initializer. This was finally adopted into standard C in C23.
gcc and clang provide the "__auto_type" alias keyword as an extension for pre-C23, however, there is no reason to pollute the bulk of the source base with this temporary keyword; instead define "auto" as a macro unless the compiler is running in C23+ mode.
This macro is added in <linux/compiler_types.h> because that header is included in some of the tools headers, wheres <linux/compiler.h> is not as it has a bunch of very kernel-specific things in it.
[ Cc: stable to reduce potential backporting burden. ]
--- include/linux/compiler_types.h | 13 +++++++++++++ 1 file changed, 13 insertions(+)
include/linux/compiler_types.h +13 -0
@@ -5,6 +5,19 @@#ifndef __ASSEMBLY__/* +* C23 introduces "auto" as a standard way to define type-inferred +* variables, but "auto" has been a (useless) keyword even since K&R C, +* so it has always been "namespace reserved." +* +* Until at some future time we require C23 support, we need the gcc +* extension __auto_type, but there is no reason to put that elsewhere +* in the source code. +*/ +#if __STDC_VERSION__ <202311L +# define auto __auto_type +#endif + +/* * Skipped when running bindgen due to a libclang issue; * see https://github.com/rust-lang/rust-bindgen/issues/2244. */
Greg Kroah-Hartman
maintainerPATCH 602/737 kasan: refactor pcpu kasan vmalloc unpoison
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maciej Wieczor-Retman <[email protected]>
commit 6f13db031e27e88213381039032a9cc061578ea6 upstream.
A KASAN tag mismatch, possibly causing a kernel panic, can be observed on systems with a tag-based KASAN enabled and with multiple NUMA nodes. It was reported on arm64 and reproduced on x86. It can be explained in the following points:
1. There can be more than one virtual memory chunk.
2. Chunk's base address has a tag.
3. The base address points at the first chunk and thus inherits the tag of the first chunk.
4. The subsequent chunks will be accessed with the tag from the first chunk.
5. Thus, the subsequent chunks need to have their tag set to match that of the first chunk.
Refactor code by reusing __kasan_unpoison_vmalloc in a new helper in preparation for the actual fix.
--- include/linux/kasan.h | 15 +++++++++++++++ mm/kasan/common.c | 17 +++++++++++++++++ mm/vmalloc.c | 4 +--- 3 files changed, 33 insertions(+), 3 deletions(-)
include/linux/kasan.h +15 -0
@@ -423,6 +423,16 @@ static __always_inline void kasan_poison__kasan_poison_vmalloc (start, size); } +void __kasan_unpoison_vmap_areas (struct vm_struct **vms,int nr_vms, +kasan_vmalloc_flags_t flags); +static __always_inline void +kasan_unpoison_vmap_areas (struct vm_struct **vms,int nr_vms, +kasan_vmalloc_flags_t flags) +{ +if (kasan_enabled ()) +__kasan_unpoison_vmap_areas (vms, nr_vms, flags); +} +#else /* CONFIG_KASAN_VMALLOC */ static inline void kasan_populate_early_vm_area_shadow(void *start,
@@ -446,6 +456,11 @@ static inline void *kasan_unpoison_vmallstatic inline void kasan_poison_vmalloc (const void *start,unsigned long size) { } +static __always_inline void +kasan_unpoison_vmap_areas (struct vm_struct **vms,int nr_vms, +kasan_vmalloc_flags_t flags) +{ } +#endif /* CONFIG_KASAN_VMALLOC */ #if (defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS)) && \
mm/kasan/common.c +17 -0
@@ -26,6 +26,7 @@#include <linux/string.h> #include <linux/types.h> #include <linux/bug.h> +#include <linux/vmalloc.h> #include "kasan.h" #include "../slab.h"
@@ -450,3 +451,19 @@ bool __kasan_check_byte(const void *addr }return true; } + +#ifdef CONFIG_KASAN_VMALLOC +void __kasan_unpoison_vmap_areas (struct vm_struct **vms,int nr_vms, +kasan_vmalloc_flags_t flags) +{ +unsigned long size; +void *addr; +int area; + +for (area =0 ; area < nr_vms ; area++) { + size = vms[area]->size; + addr = vms[area]->addr; + vms[area]->addr =__kasan_unpoison_vmalloc (addr, size, flags); + } +} +#endif
mm/vmalloc.c +1 -3
@@ -4196,9 +4196,7 @@ retry:* With hardware tag-based KASAN, marking is skipped for * non-VM_ALLOC mappings, see __kasan_unpoison_vmalloc(). */ -for (area =0 ; area < nr_vms; area++) - vms[area]->addr =kasan_unpoison_vmalloc (vms[area]->addr, - vms[area]->size,KASAN_VMALLOC_PROT_NORMAL ); +kasan_unpoison_vmap_areas (vms, nr_vms,KASAN_VMALLOC_PROT_NORMAL );kfree (vas);return vms;
Greg Kroah-Hartman
maintainerPATCH 603/737 idr: fix idr_alloc() returning an ID out of range
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Wilcox (Oracle) <[email protected]>
commit c6e8e595a0798ad67da0f7bebaf69c31ef70dfff upstream.
If you use an IDR with a non-zero base, and specify a range that lies entirely below the base, 'max - base' becomes very large and idr_get_free() can return an ID that lies outside of the requested range.
--- lib/idr.c | 2 ++ tools/testing/radix-tree/idr-test.c | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+)
lib/idr.c +2 -0
@@ -40,6 +40,8 @@ int idr_alloc_u32(struct idr *idr, voidif (WARN_ON_ONCE (!(idr->idr_rt.xa_flags &ROOT_IS_IDR ))) idr->idr_rt.xa_flags |=IDR_RT_MARKER ; +if (max < base) +return -ENOSPC ; id = (id < base) ?0 : id - base;radix_tree_iter_init (&iter, id);
tools/testing/radix-tree/idr-test.c +21 -0
@@ -57,6 +57,26 @@ void idr_alloc_test(void)idr_destroy (&idr); } +void idr_alloc2_test (void ) +{ +int id; +struct idr idr =IDR_INIT_BASE (idr,1 ); + + id =idr_alloc (&idr, idr_alloc2_test,0 ,1 ,GFP_KERNEL ); +assert (id == -ENOSPC ); + + id =idr_alloc (&idr, idr_alloc2_test,1 ,2 ,GFP_KERNEL ); +assert (id ==1 ); + + id =idr_alloc (&idr, idr_alloc2_test,0 ,1 ,GFP_KERNEL ); +assert (id == -ENOSPC ); + + id =idr_alloc (&idr, idr_alloc2_test,0 ,2 ,GFP_KERNEL ); +assert (id == -ENOSPC ); + +idr_destroy (&idr); +} +void idr_replace_test (void ) {DEFINE_IDR (idr);
@@ -409,6 +429,7 @@ void idr_checks(void)idr_replace_test ();idr_alloc_test (); +idr_alloc2_test ();idr_null_test ();idr_nowait_test ();idr_get_next_test (0 );
Greg Kroah-Hartman
maintainerPATCH 604/737 x86/microcode/AMD: Fix Entrysign revision check for Zen5/Strix Halo
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rong Zhang <[email protected]>
commit 150b1b97e27513535dcd3795d5ecd28e61b6cb8c upstream.
Zen5 also contains family 1Ah, models 70h-7Fh, which are mistakenly missing from cpu_has_entrysign(). Add the missing range.
--- arch/x86/kernel/cpu/microcode/amd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kernel/cpu/microcode/amd.c +1 -1
@@ -237,7 +237,7 @@ static bool cpu_has_entrysign(void)if (fam ==0x1a ) {if (model <=0x2f || (0x40 <= model && model <=0x4f ) || - (0x60 <= model && model <=0x6f )) + (0x60 <= model && model <=0x7f ))return true; }
Greg Kroah-Hartman
maintainerPATCH 605/737 tools/mm/page_owner_sort: fix timestamp comparison for stable sorting
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kaushlendra Kumar <[email protected]>
commit 7013803444dd3bbbe28fd3360c084cec3057c554 upstream.
The ternary operator in compare_ts() returns 1 when timestamps are equal, causing unstable sorting behavior. Replace with explicit three-way comparison that returns 0 for equal timestamps, ensuring stable qsort ordering and consistent output.
--- tools/mm/page_owner_sort.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
tools/mm/page_owner_sort.c +5 -1
@@ -178,7 +178,11 @@ static int compare_ts(const void *p1, co {const struct block_list *l1 = p1, *l2 = p2; -return l1->ts_nsec < l2->ts_nsec ?-1 :1 ; +if (l1->ts_nsec < l2->ts_nsec) +return -1 ; +if (l1->ts_nsec > l2->ts_nsec) +return 1 ; +return 0 ; }static int compare_free_ts (const void *p1,const void *p2)
Greg Kroah-Hartman
maintainerPATCH 606/737 samples/ftrace: Adjust LoongArch register restore order in direct calls
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chenghao Duan <[email protected]>
commit bb85d206be208bbf834883e948125a35ac59993a upstream.
Ensure that in the ftrace direct call logic, the CPU register state (with ra = parent return address) is restored to the correct state after the execution of the custom trampoline function and before returning to the traced function. Additionally, guarantee the correctness of the jump logic for jr t0 (traced function address).
--- samples/ftrace/ftrace-direct-modify.c | 8 ++++---- samples/ftrace/ftrace-direct-multi-modify.c | 8 ++++---- samples/ftrace/ftrace-direct-multi.c | 4 ++-- samples/ftrace/ftrace-direct-too.c | 4 ++-- samples/ftrace/ftrace-direct.c | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-)
samples/ftrace/ftrace-direct-modify.c +4 -4
@@ -141,8 +141,8 @@ asm (" st.d $t0, $sp, 0\n" " st.d $ra, $sp, 8\n" " bl my_direct_func1\n" -" ld.d $t0, $sp, 0\n" -" ld.d $ra, $sp, 8\n" +" ld.d $ra, $sp, 0\n" +" ld.d $t0, $sp, 8\n" " addi.d $sp, $sp, 16\n" " jr $t0\n" " .size my_tramp1, .-my_tramp1\n"
@@ -154,8 +154,8 @@ asm (" st.d $t0, $sp, 0\n" " st.d $ra, $sp, 8\n" " bl my_direct_func2\n" -" ld.d $t0, $sp, 0\n" -" ld.d $ra, $sp, 8\n" +" ld.d $ra, $sp, 0\n" +" ld.d $t0, $sp, 8\n" " addi.d $sp, $sp, 16\n" " jr $t0\n" " .size my_tramp2, .-my_tramp2\n"
samples/ftrace/ftrace-direct-multi-modify.c +4 -4
@@ -158,8 +158,8 @@ asm (" move $a0, $t0\n" " bl my_direct_func1\n" " ld.d $a0, $sp, 0\n" -" ld.d $t0, $sp, 8\n" -" ld.d $ra, $sp, 16\n" +" ld.d $ra, $sp, 8\n" +" ld.d $t0, $sp, 16\n" " addi.d $sp, $sp, 32\n" " jr $t0\n" " .size my_tramp1, .-my_tramp1\n"
@@ -174,8 +174,8 @@ asm (" move $a0, $t0\n" " bl my_direct_func2\n" " ld.d $a0, $sp, 0\n" -" ld.d $t0, $sp, 8\n" -" ld.d $ra, $sp, 16\n" +" ld.d $ra, $sp, 8\n" +" ld.d $t0, $sp, 16\n" " addi.d $sp, $sp, 32\n" " jr $t0\n" " .size my_tramp2, .-my_tramp2\n"
samples/ftrace/ftrace-direct-multi.c +2 -2
@@ -106,8 +106,8 @@ asm (" move $a0, $t0\n" " bl my_direct_func\n" " ld.d $a0, $sp, 0\n" -" ld.d $t0, $sp, 8\n" -" ld.d $ra, $sp, 16\n" +" ld.d $ra, $sp, 8\n" +" ld.d $t0, $sp, 16\n" " addi.d $sp, $sp, 32\n" " jr $t0\n" " .size my_tramp, .-my_tramp\n"
samples/ftrace/ftrace-direct-too.c +2 -2
@@ -115,8 +115,8 @@ asm (" ld.d $a0, $sp, 0\n" " ld.d $a1, $sp, 8\n" " ld.d $a2, $sp, 16\n" -" ld.d $t0, $sp, 24\n" -" ld.d $ra, $sp, 32\n" +" ld.d $ra, $sp, 24\n" +" ld.d $t0, $sp, 32\n" " addi.d $sp, $sp, 48\n" " jr $t0\n" " .size my_tramp, .-my_tramp\n"
samples/ftrace/ftrace-direct.c +2 -2
@@ -100,8 +100,8 @@ asm (" st.d $ra, $sp, 16\n" " bl my_direct_func\n" " ld.d $a0, $sp, 0\n" -" ld.d $t0, $sp, 8\n" -" ld.d $ra, $sp, 16\n" +" ld.d $ra, $sp, 8\n" +" ld.d $t0, $sp, 16\n" " addi.d $sp, $sp, 32\n" " jr $t0\n" " .size my_tramp, .-my_tramp\n"
Greg Kroah-Hartman
maintainerPATCH 607/737 RDMA/core: Check for the presence of LS_NLA_TYPE_DGID correctly
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Gunthorpe <[email protected]>
commit a7b8e876e0ef0232b8076972c57ce9a7286b47ca upstream.
The netlink response for RDMA_NL_LS_OP_IP_RESOLVE should always have a LS_NLA_TYPE_DGID attribute, it is invalid if it does not.
Use the nl parsing logic properly and call nla_parse_deprecated() to fill the nlattrs array and then directly index that array to get the data for the DGID. Just fail if it is NULL.
Remove the for loop searching for the nla, and squash the validation and parsing into one function.
Fixes an uninitialized read from the stack triggered by userspace if it does not provide the DGID to a kernel initiated RDMA_NL_LS_OP_IP_RESOLVE query.
BUG: KMSAN: uninit-value in hex_byte_pack include/linux/hex.h:13 [inline]
BUG: KMSAN: uninit-value in ip6_string+0xef4/0x13a0 lib/vsprintf.c:1490
hex_byte_pack include/linux/hex.h:13 [inline]
ip6_string+0xef4/0x13a0 lib/vsprintf.c:1490
ip6_addr_string+0x18a/0x3e0 lib/vsprintf.c:1509
ip_addr_string+0x245/0xee0 lib/vsprintf.c:1633
pointer+0xc09/0x1bd0 lib/vsprintf.c:2542
vsnprintf+0xf8a/0x1bd0 lib/vsprintf.c:2930
vprintk_store+0x3ae/0x1530 kernel/printk/printk.c:2279
vprintk_emit+0x307/0xcd0 kernel/printk/printk.c:2426
vprintk_default+0x3f/0x50 kernel/printk/printk.c:2465
vprintk+0x36/0x50 kernel/printk/printk_safe.c:82
_printk+0x17e/0x1b0 kernel/printk/printk.c:2475
ib_nl_process_good_ip_rsep drivers/infiniband/core/addr.c:128 [inline]
ib_nl_handle_ip_res_resp+0x963/0x9d0 drivers/infiniband/core/addr.c:141
rdma_nl_rcv_msg drivers/infiniband/core/netlink.c:-1 [inline]
rdma_nl_rcv_skb drivers/infiniband/core/netlink.c:239 [inline]
rdma_nl_rcv+0xefa/0x11c0 drivers/infiniband/core/netlink.c:259
netlink_unicast_kernel net/netlink/af_netlink.c:1320 [inline]
netlink_unicast+0xf04/0x12b0 net/netlink/af_netlink.c:1346
netlink_sendmsg+0x10b3/0x1250 net/netlink/af_netlink.c:1896
sock_sendmsg_nosec net/socket.c:714 [inline]
__sock_sendmsg+0x333/0x3d0 net/socket.c:729
____sys_sendmsg+0x7e0/0xd80 net/socket.c:2617
___sys_sendmsg+0x271/0x3b0 net/socket.c:2671
__sys_sendmsg+0x1aa/0x300 net/socket.c:2703
__compat_sys_sendmsg net/compat.c:346 [inline]
__do_compat_sys_sendmsg net/compat.c:353 [inline]
__se_compat_sys_sendmsg net/compat.c:350 [inline]
__ia32_compat_sys_sendmsg+0xa4/0x100 net/compat.c:350
ia32_sys_call+0x3f6c/0x4310 arch/x86/include/generated/asm/syscalls_32.h:371
do_syscall_32_irqs_on arch/x86/entry/syscall_32.c:83 [inline]
__do_fast_syscall_32+0xb0/0x150 arch/x86/entry/syscall_32.c:306
do_fast_syscall_32+0x38/0x80 arch/x86/entry/syscall_32.c:331
do_SYSENTER_32+0x1f/0x30 arch/x86/entry/syscall_32.c:3--- drivers/infiniband/core/addr.c | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-)
drivers/infiniband/core/addr.c +10 -23
@@ -80,37 +80,25 @@ static const struct nla_policy ib_nl_add .min = sizeof(struct rdma_nla_ls_gid)}, }; -static inline bool ib_nl_is_good_ip_resp (const struct nlmsghdr *nlh) +static void ib_nl_process_ip_rsep (const struct nlmsghdr *nlh) {struct nlattr *tb[LS_NLA_TYPE_MAX ] = {}; +union ib_gid gid; +struct addr_req *req; +int found =0 ;int ret;if (nlh->nlmsg_flags &RDMA_NL_LS_F_ERR ) -return false; +return ; ret =nla_parse_deprecated (tb,LS_NLA_TYPE_MAX -1 ,nlmsg_data (nlh),nlmsg_len (nlh), ib_nl_addr_policy,NULL );if (ret) -return false; - -return true; -} - -static void ib_nl_process_good_ip_rsep (const struct nlmsghdr *nlh) -{ -const struct nlattr *head, *curr; -union ib_gid gid; -struct addr_req *req; -int len, rem; -int found =0 ; - - head = (const struct nlattr *)nlmsg_data (nlh); - len =nlmsg_len (nlh); +return ; -nla_for_each_attr (curr, head, len, rem) { -if (curr->nla_type ==LS_NLA_TYPE_DGID ) -memcpy (&gid,nla_data (curr),nla_len (curr)); - } +if (!tb[LS_NLA_TYPE_DGID ]) +return ; +memcpy (&gid,nla_data (tb[LS_NLA_TYPE_DGID ]),sizeof (gid));spin_lock_bh (&lock);list_for_each_entry (req, &req_list, list) {
@@ -137,8 +125,7 @@ int ib_nl_handle_ip_res_resp(struct sk_b !(NETLINK_CB(skb).sk))return -EPERM ; -if (ib_nl_is_good_ip_resp (nlh)) -ib_nl_process_good_ip_rsep (nlh); +ib_nl_process_ip_rsep (nlh);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 608/737 RDMA/cm: Fix leaking the multicast GID table reference
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Gunthorpe <[email protected]>
commit 57f3cb6c84159d12ba343574df2115fb18dd83ca upstream.
If the CM ID is destroyed while the CM event for multicast creating is still queued the cancel_work_sync() will prevent the work from running which also prevents destroying the ah_attr. This leaks a refcount and triggers a WARN:
GID entry ref leak for dev syz1 index 2 ref=573
WARNING: CPU: 1 PID: 655 at drivers/infiniband/core/cache.c:809 release_gid_table drivers/infiniband/core/cache.c:806 [inline] WARNING: CPU: 1 PID: 655 at drivers/infiniband/core/cache.c:809 gid_table_release_one+0x284/0x3cc drivers/infiniband/core/cache.c:886
Destroy the ah_attr after canceling the work, it is safe to call this twice.
--- drivers/infiniband/core/cma.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/infiniband/core/cma.c +3 -0
@@ -1993,6 +1993,7 @@ static void destroy_mc(struct rdma_id_prib_sa_free_multicast (mc->sa_mc);if (rdma_protocol_roce (id_priv->id.device, id_priv->id.port_num)) { +struct rdma_cm_event *event = &mc->iboe_join.event;struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;struct net_device *ndev =NULL ;
@@ -2015,6 +2016,8 @@ static void destroy_mc(struct rdma_id_prdev_put (ndev);cancel_work_sync (&mc->iboe_join.work); +if (event->event ==RDMA_CM_EVENT_MULTICAST_JOIN ) +rdma_destroy_ah_attr (&event->param.ud.ah_attr); }kfree (mc); }
Greg Kroah-Hartman
maintainerPATCH 609/737 e1000: fix OOB in e1000_tbi_should_accept()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <[email protected]>
commit 9c72a5182ed92904d01057f208c390a303f00a0f upstream.
In e1000_tbi_should_accept() we read the last byte of the frame via 'data[length - 1]' to evaluate the TBI workaround. If the descriptor- reported length is zero or larger than the actual RX buffer size, this read goes out of bounds and can hit unrelated slab objects. The issue is observed from the NAPI receive path (e1000_clean_rx_irq):
==================================================================
BUG: KASAN: slab-out-of-bounds in e1000_tbi_should_accept+0x610/0x790 Read of size 1 at addr ffff888014114e54 by task sshd/363 CPU: 0 PID: 363 Comm: sshd Not tainted 5.18.0-rc1 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-59-gc9ba5276e321-prebuilt.qemu.org 04/01/2014 Call Trace: <IRQ> dump_stack_lvl+0x5a/0x74 print_address_description+0x7b/0x440 print_report+0x101/0x200 kasan_report+0xc1/0xf0 e1000_tbi_should_accept+0x610/0x790 e1000_clean_rx_irq+0xa8c/0x1110 e1000_clean+0xde2/0x3c10 __napi_poll+0x98/0x380 net_rx_action+0x491/0xa20 __do_softirq+0x2c9/0x61d do_softirq+0xd1/0x120 </IRQ> <TASK> __local_bh_enable_ip+0xfe/0x130 ip_finish_output2+0x7d5/0xb00 __ip_queue_xmit+0xe24/0x1ab0 __tcp_transmit_skb+0x1bcb/0x3340 tcp_write_xmit+0x175d/0x6bd0 __tcp_push_pending_frames+0x7b/0x280 tcp_sendmsg_locked+0x2e4f/0x32d0 tcp_sendmsg+0x24/0x40 sock_write_iter+0x322/0x430 vfs_write+0x56c/0xa60 ksys_write+0xd1/0x190 do_syscall_64+0x43/0x90 entry_SYSCALL_64_after_hwframe+0x44/0xae RIP: 0033:0x7f511b476b10 Code: 73 01 c3 48 8b 0d 88 d3 2b 00 f7 d8 64 89 01 48 83 c8 ff c3 66 0f 1f 44 00 00 83 3d f9 2b 2c 00 00 75 10 b8 01 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 31 c3 48 83 ec 08 e8 8e 9b 01 00 48 89 04 24 RSP: 002b:00007ffc9211d4e8 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 RAX: ffffffffffffffda RBX: 0000000000004024 RCX: 00007f511b476b10 RDX: 0000000000004024 RSI: 0000559a9385962c RDI: 0000000000000003 RBP: 0000559a9383a400 R08: fffffffffffffff0 R09: 0000000000004f00 R10: 0000000000000070 R11: 0000000000000246 R12: 0000000000000000 R13: 00007ffc9211d57f R14: 0000559a9347bde7 R15: 0000000000000003 </TASK> Allocated by task 1: __kasan_krealloc+0x131/0x1c0 krealloc+0x90/0xc0 add_sysfs_param+0xcb/0x8a0 kernel_add_sysfs_param+0x81/0xd4 param_sysfs_builtin+0x138/0x1a6 param_sysfs_init+0x57/0x5b do_one_initcall+0x104/0x250 do_initcall_level+0x102/0x132 do_initcalls+0x46/0x74 kernel_init_freeable+0x28f/0x393 kernel_init+0x14/0x1a0 ret_from_fork+0x22/0x30 The buggy address belongs to the object at ffff888014114000 which belongs to the cache kmalloc-2k of size 2048 The buggy address is located 1620 bytes to the right of 2048-byte region [ffff888014114000, ffff888014114800] The buggy address belongs to the physical page: page:ffffea0000504400 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x14110 head:ffffea0000504400 order:3 compound_mapcount:0 compound_pincount:0 flags: 0x100000000010200(slab|head|node=0|zone=1) raw: 0100000000010200 0000000000000000 dead000000000001 ffff888013442000 raw: 0000000000000000 0000000000080008 00000001ffffffff 0000000000000000 page dumped because: kasan: bad access detected ==================================================================
This happens because the TBI check unconditionally dereferences the last byte without validating the reported length first:
u8 last_byte = *(data + length - 1);
Fix by rejecting the frame early if the length is zero, or if it exceeds adapter->rx_buffer_len. This preserves the TBI workaround semantics for valid frames and prevents touching memory beyond the RX buffer.
--- drivers/net/ethernet/intel/e1000/e1000_main.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
drivers/net/ethernet/intel/e1000/e1000_main.c +9 -1
@@ -4091,7 +4091,15 @@ static bool e1000_tbi_should_accept(stru u32 length, const u8 *data) { struct e1000_hw *hw = &adapter->hw; -u8 last_byte = *(data + length -1 ); +u8 last_byte; + +/* Guard against OOB on data[length - 1] */ +if (unlikely (!length)) +return false; +/* Upper bound: length must not exceed rx_buffer_len */ +if (unlikely (length > adapter->rx_buffer_len)) +return false; + last_byte = *(data + length -1 );if (TBI_ACCEPT (hw, status, errors, length, last_byte)) {unsigned long irq_flags;
Greg Kroah-Hartman
maintainerPATCH 610/737 fjes: Add missing iounmap in fjes_hw_init()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haoxiang Li <[email protected]>
commit 15ef641a0c6728d25a400df73922e80ab2cf029c upstream.
In error paths, add fjes_hw_iounmap() to release the resource acquired by fjes_hw_iomap(). Add a goto label to do so.
--- drivers/net/fjes/fjes_hw.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
drivers/net/fjes/fjes_hw.c +9 -3
@@ -334,7 +334,7 @@ int fjes_hw_init(struct fjes_hw *hw) ret =fjes_hw_reset (hw);if (ret) -return ret; + goto err_iounmap;fjes_hw_set_irqmask (hw,REG_ICTL_MASK_ALL , true);
@@ -347,8 +347,10 @@ int fjes_hw_init(struct fjes_hw *hw) hw->max_epid =fjes_hw_get_max_epid (hw); hw->my_epid =fjes_hw_get_my_epid (hw); -if ((hw->max_epid ==0 ) || (hw->my_epid >= hw->max_epid)) -return -ENXIO ; +if ((hw->max_epid ==0 ) || (hw->my_epid >= hw->max_epid)) { + ret = -ENXIO ; + goto err_iounmap; + } ret =fjes_hw_setup (hw);
@@ -356,6 +358,10 @@ int fjes_hw_init(struct fjes_hw *hw) hw->hw_info.trace_size =FJES_DEBUG_BUFFER_SIZE ;return ret; + +err_iounmap: +fjes_hw_iounmap (hw); +return ret; }void fjes_hw_exit (struct fjes_hw *hw)
Greg Kroah-Hartman
maintainerPATCH 611/737 LoongArch: BPF: Zero-extend bpf_tail_call() index
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hengqi Chen <[email protected]>
commit eb71f5c433e1c6dff089b315881dec40a88a7baf upstream.
The bpf_tail_call() index should be treated as a u32 value. Let's zero-extend it to avoid calling wrong BPF progs. See similar fixes for x86 [1]) and arm64 ([2]) for more details.
[1]: https://github.com/torvalds/linux/commit/90caccdd8cc0215705f18b92771b449b01e2474a
[2]: https://github.com/torvalds/linux/commit/16338a9b3ac30740d49f5dfed81bac0ffa53b9c7
--- arch/loongarch/net/bpf_jit.c | 2 ++ 1 file changed, 2 insertions(+)
arch/loongarch/net/bpf_jit.c +2 -0
@@ -226,6 +226,8 @@ static int emit_bpf_tail_call(struct jit* goto out; */ tc_ninsn = insn ? ctx->offset[insn+1 ] - ctx->offset[insn] : ctx->offset[0 ]; +emit_zext_32 (ctx, a2, true); + off = offsetof(struct bpf_array, map.max_entries);emit_insn (ctx, ldwu, t1, a1, off);/* bgeu $a2, $t1, jmp_offset */
Greg Kroah-Hartman
maintainerPATCH 612/737 LoongArch: BPF: Sign extend kfunc call arguments
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hengqi Chen <[email protected]>
commit 3f5a238f24d7b75f9efe324d3539ad388f58536e upstream.
The kfunc calls are native calls so they should follow LoongArch calling conventions. Sign extend its arguments properly to avoid kernel panic. This is done by adding a new emit_abi_ext() helper. The emit_abi_ext() helper performs extension in place meaning a value already store in the target register (Note: this is different from the existing sign_extend() helper and thus we can't reuse it).
--- arch/loongarch/net/bpf_jit.c | 16 ++++++++++++++++ arch/loongarch/net/bpf_jit.h | 26 ++++++++++++++++++++++++++ 2 files changed, 42 insertions(+)
arch/loongarch/net/bpf_jit.c +16 -0
@@ -834,6 +834,22 @@ static int build_insn(const struct bpf_iif (ret <0 )return ret; +if (insn->src_reg ==BPF_PSEUDO_KFUNC_CALL ) { +const struct btf_func_model *m; +int i; + + m =bpf_jit_find_kfunc_model (ctx->prog, insn); +if (!m) +return -EINVAL ; + +for (i =0 ; i < m->nr_args; i++) { +u8 reg = regmap[BPF_REG_1 + i]; +bool sign = m->arg_flags[i] &BTF_FMODEL_SIGNED_ARG ; + +emit_abi_ext (ctx, reg, m->arg_size[i], sign); + } + } +move_addr (ctx, t1, func_addr);emit_insn (ctx, jirl,LOONGARCH_GPR_RA , t1,0 );
arch/loongarch/net/bpf_jit.h +26 -0
@@ -87,6 +87,32 @@ static inline void emit_sext_32(struct jemit_insn (ctx, addiw, reg, reg,0 ); } +/* Emit proper extension according to ABI requirements. +* Note that it requires a value of size `size` already resides in register `reg`. +*/ +static inline void emit_abi_ext (struct jit_ctx *ctx,int reg,u8 size,bool sign) +{ +/* ABI requires unsigned char/short to be zero-extended */ +if (!sign && (size ==1 || size ==2 )) +return ; + +switch (size) { +case 1 : +emit_insn (ctx, extwb, reg, reg); +break ; +case 2 : +emit_insn (ctx, extwh, reg, reg); +break ; +case 4 : +emit_insn (ctx, addiw, reg, reg,0 ); +break ; +case 8 : +break ; +default : +pr_warn ("bpf_jit: invalid size %d for extension\n" , size); + } +} +static inline void move_addr (struct jit_ctx *ctx,enum loongarch_gpr rd,u64 addr) {u64 imm_11_0, imm_31_12, imm_51_32, imm_63_52;
Greg Kroah-Hartman
maintainerPATCH 613/737 nfsd: Drop the client reference in client_states_open()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haoxiang Li <[email protected]>
commit 1f941b2c23fd34c6f3b76d36f9d0a2528fa92b8f upstream.
In error path, call drop_client() to drop the reference obtained by get_nfsdfs_clp().
--- fs/nfsd/nfs4state.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
fs/nfsd/nfs4state.c +3 -1
@@ -2801,8 +2801,10 @@ static int client_states_open(struct inoreturn -ENXIO ; ret =seq_open (file, &states_seq_ops); -if (ret) +if (ret) { +drop_client (clp);return ret; + } s = file->private_data; s->private = clp;return 0 ;
Greg Kroah-Hartman
maintainerPATCH 614/737 net: usb: sr9700: fix incorrect command used to write single register
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ethan Nelson-Moore <[email protected]>
commit fa0b198be1c6775bc7804731a43be5d899d19e7a upstream.
This fixes the device failing to initialize with "error reading MAC address" for me, probably because the incorrect write of NCR_RST to SR_NCR is not actually resetting the device.
--- drivers/net/usb/sr9700.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/usb/sr9700.c +2 -2
@@ -52,7 +52,7 @@ static int sr_read_reg(struct usbnet *destatic int sr_write_reg (struct usbnet *dev,u8 reg,u8 value) { -return usbnet_write_cmd (dev,SR_WR_REGS ,SR_REQ_WR_REG , +return usbnet_write_cmd (dev,SR_WR_REG ,SR_REQ_WR_REG , value, reg,NULL ,0 ); }
@@ -65,7 +65,7 @@ static void sr_write_async(struct usbnetstatic void sr_write_reg_async (struct usbnet *dev,u8 reg,u8 value) { -usbnet_write_cmd_async (dev,SR_WR_REGS ,SR_REQ_WR_REG , +usbnet_write_cmd_async (dev,SR_WR_REG ,SR_REQ_WR_REG , value, reg,NULL ,0 ); }
Greg Kroah-Hartman
maintainerPATCH 615/737 net: nfc: fix deadlock between nfc_unregister_device and rfkill_fop_write
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Deepanshu Kartikey <[email protected]>
commit 1ab526d97a57e44d26fadcc0e9adeb9c0c0182f5 upstream.
A deadlock can occur between nfc_unregister_device() and rfkill_fop_write() due to lock ordering inversion between device_lock and rfkill_global_mutex.
The problematic lock order is:
Thread A (rfkill_fop_write):
rfkill_fop_write()
mutex_lock(&rfkill_global_mutex)
rfkill_set_block()
nfc_rfkill_set_block()
nfc_dev_down()
device_lock(&dev->dev) <- waits for device_lockThread B (nfc_unregister_device):
nfc_unregister_device()
device_lock(&dev->dev)
rfkill_unregister()
mutex_lock(&rfkill_global_mutex) <- waits for rfkill_global_mutex
This creates a classic ABBA deadlock scenario.
Fix this by moving rfkill_unregister() and rfkill_destroy() outside the device_lock critical section. Store the rfkill pointer in a local variable before releasing the lock, then call rfkill_unregister() after releasing device_lock.
This change is safe because rfkill_fop_write() holds rfkill_global_mutex while calling the rfkill callbacks, and rfkill_unregister() also acquires rfkill_global_mutex before cleanup. Therefore, rfkill_unregister() will wait for any ongoing callback to complete before proceeding, and device_del() is only called after rfkill_unregister() returns, preventing any use-after-free.
The similar lock ordering in nfc_register_device() (device_lock -> rfkill_global_mutex via rfkill_register) is safe because during registration the device is not yet in rfkill_list, so no concurrent rfkill operations can occur on this device.
--- net/nfc/core.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
net/nfc/core.c +7 -2
@@ -1154,6 +1154,7 @@ EXPORT_SYMBOL(nfc_register_device);void nfc_unregister_device (struct nfc_dev *dev) {int rc; +struct rfkill *rfk =NULL ;pr_debug ("dev_name=%s\n" ,dev_name (&dev->dev));
@@ -1164,13 +1165,17 @@ void nfc_unregister_device(struct nfc_dedevice_lock (&dev->dev);if (dev->rfkill) { -rfkill_unregister (dev->rfkill); -rfkill_destroy (dev->rfkill); + rfk = dev->rfkill; dev->rfkill =NULL ; } dev->shutting_down = true;device_unlock (&dev->dev); +if (rfk) { +rfkill_unregister (rfk); +rfkill_destroy (rfk); + } +if (dev->ops->check_presence) {del_timer_sync (&dev->check_pres_timer);cancel_work_sync (&dev->check_pres_work);
Greg Kroah-Hartman
maintainerPATCH 616/737 net: macb: Relocate mog_init_rings() callback from macb_mac_link_up() to macb_open()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiaolei Wang <[email protected]>
commit 99537d5c476cada9cf75aef9fa75579a31faadb9 upstream.
In the non-RT kernel, local_bh_disable() merely disables preemption, whereas it maps to an actual spin lock in the RT kernel. Consequently, when attempting to refill RX buffers via netdev_alloc_skb() in macb_mac_link_up(), a deadlock scenario arises as follows:
WARNING: possible circular locking dependency detected 6.18.0-08691-g2061f18ad76e #39 Not tainted
------------------------------------------------------
kworker/0:0/8 is trying to acquire lock:
ffff00080369bbe0 (&bp->lock){+.+.}-{3:3}, at: macb_start_xmit+0x808/0xb7c
but task is already holding lock:
ffff000803698e58 (&queue->tx_ptr_lock){+...}-{3:3}, at: macb_start_xmit +0x148/0xb7c
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #3 (&queue->tx_ptr_lock){+...}-{3:3}:
rt_spin_lock+0x50/0x1f0
macb_start_xmit+0x148/0xb7c
dev_hard_start_xmit+0x94/0x284
sch_direct_xmit+0x8c/0x37c
__dev_queue_xmit+0x708/0x1120
neigh_resolve_output+0x148/0x28c
ip6_finish_output2+0x2c0/0xb2c
__ip6_finish_output+0x114/0x308
ip6_output+0xc4/0x4a4
mld_sendpack+0x220/0x68c
mld_ifc_work+0x2a8/0x4f4
process_one_work+0x20c/0x5f8
worker_thread+0x1b0/0x35c
kthread+0x144/0x200
ret_from_fork+0x10/0x20-> #2 (_xmit_ETHER#2){+...}-{3:3}:
rt_spin_lock+0x50/0x1f0
sch_direct_xmit+0x11c/0x37c
__dev_queue_xmit+0x708/0x1120
neigh_resolve_output+0x148/0x28c
ip6_finish_output2+0x2c0/0xb2c
__ip6_finish_output+0x114/0x308
ip6_output+0xc4/0x4a4
mld_sendpack+0x220/0x68c
mld_ifc_work+0x2a8/0x4f4
process_one_work+0x20c/0x5f8
worker_thread+0x1b0/0x35c
kthread+0x144/0x200
ret_from_fork+0x10/0x20-> #1 ((softirq_ctrl.lock)){+.+.}-{3:3}:
lock_release+0x250/0x348
__local_bh_enable_ip+0x7c/0x240
__netdev_alloc_skb+0x1b4/0x1d8
gem_rx_refill+0xdc/0x240
gem_init_rings+0xb4/0x108
macb_mac_link_up+0x9c/0x2b4
phylink_resolve+0x170/0x614
process_one_work+0x20c/0x5f8
worker_thread+0x1b0/0x35c
kthread+0x144/0x200
ret_from_fork+0x10/0x20-> #0 (&bp->lock){+.+.}-{3:3}:
__lock_acquire+0x15a8/0x2084
lock_acquire+0x1cc/0x350
rt_spin_lock+0x50/0x1f0
macb_start_xmit+0x808/0xb7c
dev_hard_start_xmit+0x94/0x284
sch_direct_xmit+0x8c/0x37c
__dev_queue_xmit+0x708/0x1120
neigh_resolve_output+0x148/0x28c
ip6_finish_output2+0x2c0/0xb2c
__ip6_finish_output+0x114/0x308
ip6_output+0xc4/0x4a4
mld_sendpack+0x220/0x68c
mld_ifc_work+0x2a8/0x4f4
process_one_work+0x20c/0x5f8
worker_thread+0x1b0/0x35c
kthread+0x144/0x200
ret_from_fork+0x10/0x20other info that might help us debug this:
Chain exists of:
&bp->lock --> _xmit_ETHER#2 --> &queue->tx_ptr_lock
Possible unsafe locking scenario: CPU0 CPU1
---- ----
lock(&queue->tx_ptr_lock);
lock(_xmit_ETHER#2);
lock(&queue->tx_ptr_lock);
lock(&bp->lock);
*** DEADLOCK *** Call trace:
show_stack+0x18/0x24 (C)
dump_stack_lvl+0xa0/0xf0
dump_stack+0x18/0x24
print_circular_bug+0x28c/0x370
check_noncircular+0x198/0x1ac
__lock_acquire+0x15a8/0x2084
lock_acquire+0x1cc/0x350
rt_spin_lock+0x50/0x1f0
macb_start_xmit+0x808/0xb7c
dev_hard_start_xmit+0x94/0x284
sch_direct_xmit+0x8c/0x37c
__dev_queue_xmit+0x708/0x1120
neigh_resolve_output+0x148/0x28c
ip6_finish_output2+0x2c0/0xb2c
__ip6_finish_output+0x114/0x308
ip6_output+0xc4/0x4a4
mld_sendpack+0x220/0x68c
mld_ifc_work+0x2a8/0x4f4
process_one_work+0x20c/0x5f8
worker_thread+0x1b0/0x35c
kthread+0x144/0x200
ret_from_fork+0x10/0x20Notably, invoking the mog_init_rings() callback upon link establishment is unnecessary. Instead, we can exclusively call mog_init_rings() within the ndo_open() callback. This adjustment resolves the deadlock issue. Furthermore, since MACB_CAPS_MACB_IS_EMAC cases do not use mog_init_rings() when opening the network interface via at91ether_open(), moving mog_init_rings() to macb_open() also eliminates the MACB_CAPS_MACB_IS_EMAC check.
--- drivers/net/ethernet/cadence/macb_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/ethernet/cadence/macb_main.c +2 -1
@@ -759,7 +759,6 @@ static void macb_mac_link_up(struct phyl/* Initialize rings & buffers as clearing MACB_BIT(TE) in link down * cleared the pipeline and control registers. */ - bp->macbgem_ops.mog_init_rings (bp);macb_init_buffers (bp);for (q =0 , queue = bp->queues; q < bp->num_queues; ++q, ++queue)
@@ -2953,6 +2952,8 @@ static int macb_open(struct net_device * goto pm_exit; } + bp->macbgem_ops.mog_init_rings (bp); +for (q =0 , queue = bp->queues; q < bp->num_queues; ++q, ++queue) {napi_enable (&queue->napi_rx);napi_enable (&queue->napi_tx);
Greg Kroah-Hartman
maintainerPATCH 617/737 drm/amdgpu: add missing lock to amdgpu_ttm_access_memory_sdma
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pierre-Eric Pelloux-Prayer <[email protected]>
commit 4fa944255be521b1bbd9780383f77206303a3a5c upstream.
Users of ttm entities need to hold the gtt_window_lock before using them to guarantee proper ordering of jobs.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +2 -0
@@ -1495,6 +1495,7 @@ static int amdgpu_ttm_access_memory_sdmaif (r) goto out; +mutex_lock (&adev->mman.gtt_window_lock);amdgpu_res_first (abo->tbo.resource, offset, len, &src_mm); src_addr =amdgpu_ttm_domain_start (adev, bo->resource->mem_type) + src_mm.start;
@@ -1509,6 +1510,7 @@ static int amdgpu_ttm_access_memory_sdmaWARN_ON (job->ibs[0 ].length_dw > num_dw); fence =amdgpu_job_submit (job); +mutex_unlock (&adev->mman.gtt_window_lock);if (!dma_fence_wait_timeout (fence, false, adev->sdma_timeout)) r = -ETIMEDOUT ;
Greg Kroah-Hartman
maintainerPATCH 618/737 drm/msm/a6xx: Fix out of bound IO access in a6xx_get_gmu_registers
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Akhil P Oommen <[email protected]>
commit 779b68a5bf2764c8ed3aa800e41ba0d5d007e1e7 upstream.
REG_A6XX_GMU_AO_AHB_FENCE_CTRL register falls under GMU's register range. So, use gmu_write() routines to write to this register.
Patchwork: https://patchwork.freedesktop.org/patch/688993/
Message-ID: <[email protected]>
--- drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c +1 -1
@@ -834,7 +834,7 @@ static void a6xx_get_gmu_registers(strucreturn ;/* Set the fence to ALLOW mode so we can access the registers */ -gpu_write (gpu,REG_A6XX_GMU_AO_AHB_FENCE_CTRL ,0 ); +gmu_write (&a6xx_gpu->gmu,REG_A6XX_GMU_AO_AHB_FENCE_CTRL ,0 );_a6xx_get_gmu_registers (gpu, a6xx_state, &a6xx_gmu_reglist[2 ], &a6xx_state->gmu_registers[2 ], false);
Greg Kroah-Hartman
maintainerPATCH 619/737 drm/gma500: Remove unused helper psb_fbdev_fb_setcolreg()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Zimmermann <[email protected]>
commit be729f9de6c64240645dc80a24162ac4d3fe00a8 upstream.
Remove psb_fbdev_fb_setcolreg(), which hasn't been called in almost a decade.
Gma500 commit 4d8d096e9ae8 ("gma500: introduce the framebuffer support code") added the helper psb_fbdev_fb_setcolreg() for setting the fbdev palette via fbdev's fb_setcolreg callback. Later
commit 3da6c2f3b730 ("drm/gma500: use DRM_FB_HELPER_DEFAULT_OPS for fb_ops") set several default helpers for fbdev emulation, including fb_setcmap.
The fbdev subsystem always prefers fb_setcmap over fb_setcolreg. [1] Hence, the gma500 code is no longer in use and gma500 has been using drm_fb_helper_setcmap() for several years without issues.
--- drivers/gpu/drm/gma500/fbdev.c | 43 ----------------------------------------- 1 file changed, 43 deletions(-)
drivers/gpu/drm/gma500/fbdev.c +0 -43
@@ -51,48 +51,6 @@ static const struct vm_operations_struct* struct fb_ops */ -#define CMAP_TOHW (_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16) - -static int psb_fbdev_fb_setcolreg (unsigned int regno, -unsigned int red,unsigned int green, -unsigned int blue,unsigned int transp, -struct fb_info *info) -{ -struct drm_fb_helper *fb_helper = info->par; -struct drm_framebuffer *fb = fb_helper->fb; -uint32_t v; - -if (!fb) -return -ENOMEM ; - -if (regno >255 ) -return 1 ; - - red =CMAP_TOHW (red, info->var.red.length); - blue =CMAP_TOHW (blue, info->var.blue.length); - green =CMAP_TOHW (green, info->var.green.length); - transp =CMAP_TOHW (transp, info->var.transp.length); - - v = (red << info->var.red.offset) | - (green << info->var.green.offset) | - (blue << info->var.blue.offset) | - (transp << info->var.transp.offset); - -if (regno <16 ) { -switch (fb->format->cpp[0 ] *8 ) { -case 16 : - ((uint32_t *) info->pseudo_palette)[regno] = v; -break ; -case 24 : -case 32 : - ((uint32_t *) info->pseudo_palette)[regno] = v; -break ; - } - } - -return 0 ; -} -static int psb_fbdev_fb_mmap (struct fb_info *info,struct vm_area_struct *vma) {if (vma->vm_pgoff !=0 )
@@ -137,7 +95,6 @@ static const struct fb_ops psb_fbdev_fb_ .owner = THIS_MODULE, __FB_DEFAULT_IOMEM_OPS_RDWR,DRM_FB_HELPER_DEFAULT_OPS , - .fb_setcolreg = psb_fbdev_fb_setcolreg, __FB_DEFAULT_IOMEM_OPS_DRAW, .fb_mmap = psb_fbdev_fb_mmap, .fb_destroy = psb_fbdev_fb_destroy,
Greg Kroah-Hartman
maintainerPATCH 620/737 drm/mediatek: Fix device node reference leak in mtk_dp_dt_parse()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miaoqian Lin <[email protected]>
commit a846505a193d7492ad3531e33cacfca31e4bcdd1 upstream.
The function mtk_dp_dt_parse() calls of_graph_get_endpoint_by_regs() to get the endpoint device node, but fails to call of_node_put() to release the reference when the function returns. This results in a device node reference leak.
Fix this by adding the missing of_node_put() call before returning from the function.
Found via static analysis and code review.
--- drivers/gpu/drm/mediatek/mtk_dp.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/mediatek/mtk_dp.c +1 -0
@@ -1969,6 +1969,7 @@ static int mtk_dp_dt_parse(struct mtk_dp endpoint =of_graph_get_endpoint_by_regs (pdev->dev.of_node,1 ,-1 ); len =of_property_count_elems_of_size (endpoint,"data-lanes" ,sizeof (u32)); +of_node_put (endpoint);if (len <0 || len >4 || len ==3 ) {dev_err (dev,"invalid data lane size: %d\n" , len);return -EINVAL ;
Greg Kroah-Hartman
maintainerPATCH 621/737 drm/ttm: Avoid NULL pointer deref for evicted BOs
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Simon Richter <[email protected]>
commit 491adc6a0f9903c32b05f284df1148de39e8e644 upstream.
It is possible for a BO to exist that is not currently associated with a resource, e.g. because it has been evicted.
When devcoredump tries to read the contents of all BOs for dumping, we need to expect this as well -- in this case, ENODATA is recorded instead of the buffer contents.
--- drivers/gpu/drm/ttm/ttm_bo_vm.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/gpu/drm/ttm/ttm_bo_vm.c +6 -0
@@ -421,6 +421,11 @@ int ttm_bo_vm_access(struct vm_area_struif (ret)return ret; +if (!bo->resource) { + ret = -ENODATA ; + goto unlock; + } +switch (bo->resource->mem_type) {case TTM_PL_SYSTEM : fallthrough;
@@ -435,6 +440,7 @@ int ttm_bo_vm_access(struct vm_area_stru ret = -EIO ; } +unlock:ttm_bo_unreserve (bo);return ret;
Greg Kroah-Hartman
maintainerPATCH 622/737 drm/mgag200: Fix big-endian support
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: René Rebe <[email protected]>
commit 6cb31fba137d45e682ce455b8ea364f44d5d4f98 upstream.
Unlike the original, deleted Matrox mga driver, the new mgag200 driver has the XRGB frame-buffer byte swapped on big-endian "RISC" systems. Fix by enabling byte swapping "PowerPC" OPMODE for any __BIG_ENDIAN config.
--- drivers/gpu/drm/mgag200/mgag200_mode.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
drivers/gpu/drm/mgag200/mgag200_mode.c +25 -0
@@ -173,6 +173,30 @@ static void mgag200_set_startadd(structWREG_ECRT (0x00 , crtcext0); } +/* +* Set the opmode for the hardware swapper for Big-Endian processor +* support for the frame buffer aperture and DMAWIN space. +*/ +static void mgag200_set_datasiz (struct mga_device *mdev,u32 format) +{ +#if defined(__BIG_ENDIAN) +u32 opmode =RREG32 (MGAREG_OPMODE ); + + opmode &= ~(GENMASK (17 ,16 ) |GENMASK (9 ,8 ) |GENMASK (3 ,2 )); + +/* Big-endian byte-swapping */ +switch (format) { +case DRM_FORMAT_RGB565 : + opmode |=0x10100 ; +break ; +case DRM_FORMAT_XRGB8888 : + opmode |=0x20200 ; +break ; + } +WREG32 (MGAREG_OPMODE , opmode); +#endif +} +void mgag200_init_registers (struct mga_device *mdev) {u8 crtc11, misc;
@@ -502,6 +526,7 @@ void mgag200_primary_plane_helper_atomicstruct drm_atomic_helper_damage_iter iter;struct drm_rect damage; +mgag200_set_datasiz (mdev, fb->format->format);drm_atomic_helper_damage_iter_init (&iter, old_plane_state, plane_state);drm_atomic_for_each_plane_damage (&iter, &damage) {mgag200_handle_damage (mdev, shadow_plane_state->data, fb, &damage);
Greg Kroah-Hartman
maintainerPATCH 623/737 drm/msm/dpu: Add missing NULL pointer check for pingpong interface
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikolay Kuratov <[email protected]>
commit 88733a0b64872357e5ecd82b7488121503cb9cc6 upstream.
It is checked almost always in dpu_encoder_phys_wb_setup_ctl(), but in a single place the check is missing.
Also use convenient locals instead of phys_enc->* where available.
Patchwork: https://patchwork.freedesktop.org/patch/693860/
--- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c +4 -6
@@ -205,14 +205,12 @@ static void dpu_encoder_phys_wb_setup_cdif (mode_3d && hw_pp && hw_pp->merge_3d) intf_cfg.merge_3d = hw_pp->merge_3d->idx; -if (phys_enc->hw_pp->merge_3d && phys_enc->hw_pp->merge_3d->ops.setup_3d_mode) - phys_enc->hw_pp->merge_3d->ops.setup_3d_mode (phys_enc->hw_pp->merge_3d, - mode_3d); +if (hw_pp && hw_pp->merge_3d && hw_pp->merge_3d->ops.setup_3d_mode) + hw_pp->merge_3d->ops.setup_3d_mode (hw_pp->merge_3d, mode_3d);/* setup which pp blk will connect to this wb */ -if (hw_pp && phys_enc->hw_wb->ops.bind_pingpong_blk) - phys_enc->hw_wb->ops.bind_pingpong_blk (phys_enc->hw_wb, - phys_enc->hw_pp->idx); +if (hw_pp && hw_wb->ops.bind_pingpong_blk) + hw_wb->ops.bind_pingpong_blk (hw_wb, hw_pp->idx); phys_enc->hw_ctl->ops.setup_intf_cfg (phys_enc->hw_ctl, &intf_cfg); }else if (phys_enc->hw_ctl && phys_enc->hw_ctl->ops.setup_intf_cfg) {
Greg Kroah-Hartman
maintainerPATCH 624/737 drm/i915/gem: Zero-initialize the eb.vma array in i915_gem_do_execbuffer
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Niemiec <[email protected]>
commit 4fe2bd195435e71c117983d87f278112c5ab364c upstream.
Initialize the eb.vma array with values of 0 when the eb structure is first set up. In particular, this sets the eb->vma[i].vma pointers to NULL, simplifying cleanup and getting rid of the bug described below.
During the execution of eb_lookup_vmas(), the eb->vma array is successively filled up with struct eb_vma objects. This process includes calling eb_add_vma(), which might fail; however, even in the event of failure, eb->vma[i].vma is set for the currently processed buffer.
If eb_add_vma() fails, eb_lookup_vmas() returns with an error, which prompts a call to eb_release_vmas() to clean up the mess. Since eb_lookup_vmas() might fail during processing any (possibly not first) buffer, eb_release_vmas() checks whether a buffer's vma is NULL to know at what point did the lookup function fail.
In eb_lookup_vmas(), eb->vma[i].vma is set to NULL if either the helper function eb_lookup_vma() or eb_validate_vma() fails. eb->vma[i+1].vma is set to NULL in case i915_gem_object_userptr_submit_init() fails; the current one needs to be cleaned up by eb_release_vmas() at this point, so the next one is set. If eb_add_vma() fails, neither the current nor the next vma is set to NULL, which is a source of a NULL deref bug described in the issue linked in the Closes tag.
When entering eb_lookup_vmas(), the vma pointers are set to the slab poison value, instead of NULL. This doesn't matter for the actual lookup, since it gets overwritten anyway, however the eb_release_vmas() function only recognizes NULL as the stopping value, hence the pointers are being set to NULL as they go in case of intermediate failure. This patch changes the approach to filling them all with NULL at the start instead, rather than handling that manually during failure.
--- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 37 +++++++++++-------------- 1 file changed, 17 insertions(+), 20 deletions(-)
drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +17 -20
@@ -950,13 +950,13 @@ static int eb_lookup_vmas(struct i915_ex vma =eb_lookup_vma (eb, eb->exec[i].handle);if (IS_ERR (vma)) { err =PTR_ERR (vma); - goto err; +return err; } err =eb_validate_vma (eb, &eb->exec[i], vma);if (unlikely (err)) {i915_vma_put (vma); - goto err; +return err; } err =eb_add_vma (eb, ¤t_batch, i, vma);
@@ -965,19 +965,8 @@ static int eb_lookup_vmas(struct i915_exif (i915_gem_object_is_userptr (vma->obj)) { err =i915_gem_object_userptr_submit_init (vma->obj); -if (err) { -if (i +1 < eb->buffer_count) { -/* -* Execbuffer code expects last vma entry to be NULL, -* since we already initialized this entry, -* set the next value to NULL or we mess up -* cleanup handling. -*/ - eb->vma[i +1 ].vma =NULL ; - } - +if (err)return err; - } eb->vma[i].flags |= __EXEC_OBJECT_USERPTR_INIT; eb->args->flags |= __EXEC_USERPTR_USED;
@@ -985,10 +974,6 @@ static int eb_lookup_vmas(struct i915_ex }return 0 ; - -err: - eb->vma[i].vma =NULL ; -return err; }static int eb_lock_vmas (struct i915_execbuffer *eb)
@@ -3381,7 +3366,8 @@ i915_gem_do_execbuffer(struct drm_device eb.exec = exec; eb.vma = (struct eb_vma *)(exec + args->buffer_count +1 ); - eb.vma[0 ].vma =NULL ; +memset (eb.vma,0 , (args->buffer_count +1 ) *sizeof (struct eb_vma )); + eb.batch_pool =NULL ; eb.invalid_flags = __EXEC_OBJECT_UNKNOWN_FLAGS;
@@ -3590,7 +3576,18 @@ i915_gem_execbuffer2_ioctl(struct drm_deif (err)return err; -/* Allocate extra slots for use by the command parser */ +/* +* Allocate extra slots for use by the command parser. +* +* Note that this allocation handles two different arrays (the +* exec2_list array, and the eventual eb.vma array introduced in +* i915_gem_do_execbuffer()), that reside in virtually contiguous +* memory. Also note that the allocation intentionally doesn't fill the +* area with zeros, because the exec2_list part doesn't need to be, as +* it's immediately overwritten by user data a few lines below. +* However, the eb.vma part is explicitly zeroed later in +* i915_gem_do_execbuffer(). +*/ exec2_list =kvmalloc_array (count +2 ,eb_element_size (), __GFP_NOWARN |GFP_KERNEL );if (exec2_list ==NULL ) {
Greg Kroah-Hartman
maintainerPATCH 625/737 drm/nouveau/dispnv50: Dont call drm_atomic_get_crtc_state() in prepare_fb
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lyude Paul <[email protected]>
commit 560271e10b2c86e95ea35afa9e79822e4847f07a upstream.
Since we recently started warning about uses of this function after the atomic check phase completes, we've started getting warnings about this in nouveau. It appears a misplaced drm_atomic_get_crtc_state() call has been hiding in our .prepare_fb callback for a while.
So, fix this by adding a new nv50_head_atom_get_new() function and use that in our .prepare_fb callback instead.
--- drivers/gpu/drm/nouveau/dispnv50/atom.h | 13 +++++++++++++ drivers/gpu/drm/nouveau/dispnv50/wndw.c | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-)
drivers/gpu/drm/nouveau/dispnv50/atom.h +13 -0
@@ -152,8 +152,21 @@ static inline struct nv50_head_atom * nv50_head_atom_get(struct drm_atomic_state *state, struct drm_crtc *crtc) { struct drm_crtc_state *statec = drm_atomic_get_crtc_state(state, crtc); +if (IS_ERR (statec))return (void *)statec; + +return nv50_head_atom (statec); +} + +static inline struct nv50_head_atom * +nv50_head_atom_get_new (struct drm_atomic_state *state,struct drm_crtc *crtc) +{ +struct drm_crtc_state *statec =drm_atomic_get_new_crtc_state (state, crtc); + +if (!statec) +return NULL ; +return nv50_head_atom (statec); }
drivers/gpu/drm/nouveau/dispnv50/wndw.c +1 -1
@@ -567,7 +567,7 @@ nv50_wndw_prepare_fb(struct drm_plane *p asyw->image.offset[0 ] = nvbo->offset;if (wndw->func->prepare) { - asyh =nv50_head_atom_get (asyw->state.state, asyw->state.crtc); + asyh =nv50_head_atom_get_new (asyw->state.state, asyw->state.crtc);if (IS_ERR (asyh))return PTR_ERR (asyh);
Greg Kroah-Hartman
maintainerPATCH 626/737 usb: gadget: lpc32xx_udc: fix clock imbalance in error path
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 782be79e4551550d7a82b1957fc0f7347e6d461f upstream.
A recent change fixing a device reference leak introduced a clock imbalance by reusing an error path so that the clock may be disabled before having been enabled.
Note that the clock framework allows for passing in NULL clocks so there is no risk for a NULL pointer dereference.
Also drop the bogus I2C client NULL check added by the offending commit as the pointer has already been verified to be non-NULL.
--- drivers/usb/gadget/udc/lpc32xx_udc.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
drivers/usb/gadget/udc/lpc32xx_udc.c +10 -10
@@ -3027,7 +3027,7 @@ static int lpc32xx_udc_probe(struct plat pdev->dev.dma_mask = &lpc32xx_usbd_dmamask; retval =dma_set_coherent_mask (&pdev->dev,DMA_BIT_MASK (32 ));if (retval) - goto i2c_fail; + goto err_put_client; udc->board = &lpc32xx_usbddata;
@@ -3047,7 +3047,7 @@ static int lpc32xx_udc_probe(struct plat udc->udp_irq[i] =platform_get_irq (pdev, i);if (udc->udp_irq[i] <0 ) { retval = udc->udp_irq[i]; - goto i2c_fail; + goto err_put_client; } }
@@ -3055,7 +3055,7 @@ static int lpc32xx_udc_probe(struct platif (IS_ERR (udc->udp_baseaddr)) {dev_err (udc->dev,"IO map failure\n" ); retval =PTR_ERR (udc->udp_baseaddr); - goto i2c_fail; + goto err_put_client; }/* Get USB device clock */
@@ -3063,14 +3063,14 @@ static int lpc32xx_udc_probe(struct platif (IS_ERR (udc->usb_slv_clk)) {dev_err (udc->dev,"failed to acquire USB device clock\n" ); retval =PTR_ERR (udc->usb_slv_clk); - goto i2c_fail; + goto err_put_client; }/* Enable USB device clock */ retval =clk_prepare_enable (udc->usb_slv_clk);if (retval <0 ) {dev_err (udc->dev,"failed to start USB device clock\n" ); - goto i2c_fail; + goto err_put_client; }/* Setup deferred workqueue data */
@@ -3172,9 +3172,10 @@ dma_alloc_fail:dma_free_coherent (&pdev->dev,UDCA_BUFF_SIZE , udc->udca_v_base, udc->udca_p_base); i2c_fail: -if (udc->isp1301_i2c_client) -put_device (&udc->isp1301_i2c_client->dev);clk_disable_unprepare (udc->usb_slv_clk); +err_put_client: +put_device (&udc->isp1301_i2c_client->dev); +dev_err (udc->dev,"%s probe failed, %d\n" , driver_name, retval);return retval;
@@ -3199,11 +3200,10 @@ static int lpc32xx_udc_remove(struct pladma_free_coherent (&pdev->dev,UDCA_BUFF_SIZE , udc->udca_v_base, udc->udca_p_base); -if (udc->isp1301_i2c_client) -put_device (&udc->isp1301_i2c_client->dev); -clk_disable_unprepare (udc->usb_slv_clk); +put_device (&udc->isp1301_i2c_client->dev); +return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 627/737 blk-mq: add helper for checking if one CPU is mapped to specified hctx
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Lei <[email protected]>
commit 7b815817aa58d2e2101feb2fcf64c60cae0b2695 upstream.
Commit a46c27026da1 ("blk-mq: don't schedule block kworker on isolated CPUs") rules out isolated CPUs from hctx->cpumask, and hctx->cpumask should only be used for scheduling kworker.
Add helper blk_mq_cpu_mapped_to_hctx() and apply it into cpuhp handlers.
This patch avoids to forget clearing INACTIVE of hctx state in case that one isolated CPU becomes online, and fixes hang issue when allocating request from this hctx's tags.
--- block/blk-mq.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-)
block/blk-mq.c +18 -2
@@ -3617,12 +3617,28 @@ static int blk_mq_hctx_notify_offline(unreturn ret; } +/* +* Check if one CPU is mapped to the specified hctx +* +* Isolated CPUs have been ruled out from hctx->cpumask, which is supposed +* to be used for scheduling kworker only. For other usage, please call this +* helper for checking if one CPU belongs to the specified hctx +*/ +static bool blk_mq_cpu_mapped_to_hctx (unsigned int cpu, +const struct blk_mq_hw_ctx *hctx) +{ +struct blk_mq_hw_ctx *mapped_hctx =blk_mq_map_queue_type (hctx->queue, + hctx->type, cpu); + +return mapped_hctx == hctx; +} +static int blk_mq_hctx_notify_online (unsigned int cpu,struct hlist_node *node) {struct blk_mq_hw_ctx *hctx =hlist_entry_safe (node, struct blk_mq_hw_ctx, cpuhp_online); -if (cpumask_test_cpu (cpu, hctx->cpumask)) +if (blk_mq_cpu_mapped_to_hctx (cpu, hctx))clear_bit (BLK_MQ_S_INACTIVE , &hctx->state);return 0 ; }
@@ -3640,7 +3656,7 @@ static int blk_mq_hctx_notify_dead(unsigenum hctx_type type; hctx = hlist_entry_safe(node, struct blk_mq_hw_ctx, cpuhp_dead); -if (!cpumask_test_cpu (cpu, hctx->cpumask)) +if (!blk_mq_cpu_mapped_to_hctx (cpu, hctx))return 0 ; ctx =__blk_mq_get_ctx (hctx->queue, cpu);
Greg Kroah-Hartman
maintainerPATCH 628/737 tpm: Cap the number of PCR banks
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jarkko Sakkinen <[email protected]>
commit faf07e611dfa464b201223a7253e9dc5ee0f3c9e upstream.
tpm2_get_pcr_allocation() does not cap any upper limit for the number of banks. Cap the limit to eight banks so that out of bounds values coming from external I/O cause on only limited harm.
--- drivers/char/tpm/tpm-chip.c | 1 - drivers/char/tpm/tpm1-cmd.c | 5 ----- drivers/char/tpm/tpm2-cmd.c | 8 +++----- include/linux/tpm.h | 8 +++++--- 4 files changed, 8 insertions(+), 14 deletions(-)
drivers/char/tpm/tpm-chip.c +0 -1
@@ -279,7 +279,6 @@ static void tpm_dev_release(struct devickfree (chip->work_space.context_buf);kfree (chip->work_space.session_buf); -kfree (chip->allocated_banks);kfree (chip); }
drivers/char/tpm/tpm1-cmd.c +0 -5
@@ -799,11 +799,6 @@ int tpm1_pm_suspend(struct tpm_chip *chi*/ int tpm1_get_pcr_allocation (struct tpm_chip *chip) { - chip->allocated_banks =kcalloc (1 ,sizeof (*chip->allocated_banks), -GFP_KERNEL ); -if (!chip->allocated_banks) -return -ENOMEM ; - chip->allocated_banks[0 ].alg_id =TPM_ALG_SHA1 ; chip->allocated_banks[0 ].digest_size = hash_digest_size[HASH_ALGO_SHA1 ]; chip->allocated_banks[0 ].crypto_id =HASH_ALGO_SHA1 ;
drivers/char/tpm/tpm2-cmd.c +3 -5
@@ -574,11 +574,9 @@ ssize_t tpm2_get_pcr_allocation(struct t nr_possible_banks =be32_to_cpup ( (__be32 *)&buf.data[TPM_HEADER_SIZE +5 ]); - - chip->allocated_banks =kcalloc (nr_possible_banks, -sizeof (*chip->allocated_banks), -GFP_KERNEL ); -if (!chip->allocated_banks) { +if (nr_possible_banks >TPM2_MAX_PCR_BANKS ) { +pr_err ("tpm: out of bank capacity: %u > %u\n" , + nr_possible_banks,TPM2_MAX_PCR_BANKS ); rc = -ENOMEM ; goto out; }
include/linux/tpm.h +5 -3
@@ -25,7 +25,9 @@#include <crypto/hash_info.h> #define TPM_DIGEST_SIZE 20/* Max TPM v1.2 PCR size */ -#define TPM_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE + +#define TPM2_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE +#define TPM2_MAX_PCR_BANKS 8struct tpm_chip ;struct trusted_key_payload ;
@@ -51,7 +53,7 @@ enum tpm_algorithms {struct tpm_digest {u16 alg_id; -u8 digest[TPM_MAX_DIGEST_SIZE ]; +u8 digest[TPM2_MAX_DIGEST_SIZE ]; } __packed;struct tpm_bank_info {
@@ -157,7 +159,7 @@ struct tpm_chip {unsigned int groups_cnt;u32 nr_allocated_banks; -struct tpm_bank_info *allocated_banks; +struct tpm_bank_info allocated_banks[TPM2_MAX_PCR_BANKS ];#ifdef CONFIG_ACPI acpi_handle acpi_dev_handle;char ppi_version[TPM_PPI_VERSION_LEN +1 ];
Greg Kroah-Hartman
maintainerPATCH 629/737 mptcp: Initialise rcv_mss before calling tcp_send_active_reset() in mptcp_do_fastclose().
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit f07f4ea53e22429c84b20832fa098b5ecc0d4e35 ]
syzbot reported divide-by-zero in __tcp_select_window() by MPTCP socket. [0]
We had a similar issue for the bare TCP and fixed in commit 499350a5a6e7 ("tcp: initialize rcv_mss to TCP_MIN_MSS instead of 0").
Let's apply the same fix to mptcp_do_fastclose().
[0]:
Oops: divide error: 0000 [#1] SMP KASAN PTI CPU: 0 UID: 0 PID: 6068 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full) Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/25/2025 RIP: 0010:__tcp_select_window+0x824/0x1320 net/ipv4/tcp_output.c:3336 Code: ff ff ff 44 89 f1 d3 e0 89 c1 f7 d1 41 01 cc 41 21 c4 e9 a9 00 00 00 e8 ca 49 01 f8 e9 9c 00 00 00 e8 c0 49 01 f8 44 89 e0 99 <f7> 7c 24 1c 41 29 d4 48 bb 00 00 00 00 00 fc ff df e9 80 00 00 00 RSP: 0018:ffffc90003017640 EFLAGS: 00010293 RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffff88807b469e40 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000 RBP: ffffc90003017730 R08: ffff888033268143 R09: 1ffff1100664d028 R10: dffffc0000000000 R11: ffffed100664d029 R12: 0000000000000000 R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000 FS: 000055557faa0500(0000) GS:ffff888126135000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f64a1912ff8 CR3: 0000000072122000 CR4: 00000000003526f0 Call Trace: <TASK> tcp_select_window net/ipv4/tcp_output.c:281 [inline] __tcp_transmit_skb+0xbc7/0x3aa0 net/ipv4/tcp_output.c:1568 tcp_transmit_skb net/ipv4/tcp_output.c:1649 [inline] tcp_send_active_reset+0x2d1/0x5b0 net/ipv4/tcp_output.c:3836 mptcp_do_fastclose+0x27e/0x380 net/mptcp/protocol.c:2793 mptcp_disconnect+0x238/0x710 net/mptcp/protocol.c:3253 mptcp_sendmsg_fastopen+0x2f8/0x580 net/mptcp/protocol.c:1776 mptcp_sendmsg+0x1774/0x1980 net/mptcp/protocol.c:1855 sock_sendmsg_nosec net/socket.c:727 [inline] __sock_sendmsg+0xe5/0x270 net/socket.c:742 __sys_sendto+0x3bd/0x520 net/socket.c:2244 __do_sys_sendto net/socket.c:2251 [inline] __se_sys_sendto net/socket.c:2247 [inline] __x64_sys_sendto+0xde/0x100 net/socket.c:2247 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xfa/0xfa0 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7f66e998f749 Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 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 c7 c1 a8 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007ffff9acedb8 EFLAGS: 00000246 ORIG_RAX: 000000000000002c RAX: ffffffffffffffda RBX: 00007f66e9be5fa0 RCX: 00007f66e998f749 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000003 RBP: 00007ffff9acee10 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000001 R13: 00007f66e9be5fa0 R14: 00007f66e9be5fa0 R15: 0000000000000006 </TASK>
--- net/mptcp/protocol.c | 6 ++++++ 1 file changed, 6 insertions(+)
net/mptcp/protocol.c +6 -0
@@ -2823,6 +2823,12 @@ static void mptcp_do_fastclose(struct so goto unlock; subflow->send_fastclose =1 ; + +/* Initialize rcv_mss to TCP_MIN_MSS to avoid division by 0 +* issue in __tcp_select_window(), see tcp_disconnect(). +*/ +inet_csk (ssk)->icsk_ack.rcv_mss =TCP_MIN_MSS ; +tcp_send_active_reset (ssk, ssk->sk_allocation); unlock:release_sock (ssk);
Greg Kroah-Hartman
maintainerPATCH 630/737 ALSA: wavefront: Use standard print API
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
[ Upstream commit 8b4ac5429938dd5f1fbf2eea0687f08cbcccb6be ]
Use the standard print API with dev_*() instead of the old house-baked one. It gives better information and allows dynamically control of debug prints.
Stable-dep-of: 0c4a13ba8859 ("ALSA: wavefront: Fix integer overflow in sample size validation")
--- include/sound/snd_wavefront.h | 4 sound/isa/wavefront/wavefront.c | 61 +++++----- sound/isa/wavefront/wavefront_fx.c | 36 +++--- sound/isa/wavefront/wavefront_midi.c | 15 +- sound/isa/wavefront/wavefront_synth.c | 196 +++++++++++++++++----------------- 5 files changed, 158 insertions(+), 154 deletions(-)
include/sound/snd_wavefront.h +0 -4
@@ -137,8 +137,4 @@ extern int snd_wavefront_fx_ioctl (strextern int snd_wavefront_fx_open (struct snd_hwdep *,struct file *);extern int snd_wavefront_fx_release (struct snd_hwdep *,struct file *); -/* prefix in all snd_printk() delivered messages */ - -#define LOGNAME "WaveFront: " -#endif /* __SOUND_SND_WAVEFRONT_H__ */
sound/isa/wavefront/wavefront.c +31 -30
173 lines not on this page · raw message
sound/isa/wavefront/wavefront_fx.c +18 -18
@@ -38,7 +38,7 @@ wavefront_fx_idle (snd_wavefront_t *dev) }if (x &0x80 ) { -snd_printk ("FX device never idle.\n" ); +dev_err (dev->card->dev,"FX device never idle.\n" );return 0 ; }
@@ -64,14 +64,14 @@ wavefront_fx_memset (snd_wavefront_t *de unsigned short *data) {if (page <0 || page >7 ) { -snd_printk ("FX memset: " -"page must be >= 0 and <= 7\n" ); +dev_err (dev->card->dev, +"FX memset: page must be >= 0 and <= 7\n" );return -EINVAL ; }if (addr <0 || addr >0x7f ) { -snd_printk ("FX memset: " -"addr must be >= 0 and <= 7f\n" ); +dev_err (dev->card->dev, +"FX memset: addr must be >= 0 and <= 7f\n" );return -EINVAL ; }
@@ -83,7 +83,7 @@ wavefront_fx_memset (snd_wavefront_t *deoutb ((data[0 ] >>8 ), dev->fx_dsp_msb);outb ((data[0 ] &0xff ), dev->fx_dsp_lsb); -snd_printk ("FX: addr %d:%x set to 0x%x\n" , +dev_err (dev->card->dev,"FX: addr %d:%x set to 0x%x\n" , page, addr, data[0 ]); }else {
@@ -102,9 +102,9 @@ wavefront_fx_memset (snd_wavefront_t *de }if (i != cnt) { -snd_printk ("FX memset " -"(0x%x, 0x%x, 0x%lx, %d) incomplete\n" , - page, addr, (unsigned long ) data, cnt); +dev_err (dev->card->dev, +"FX memset (0x%x, 0x%x, 0x%lx, %d) incomplete\n" , + page, addr, (unsigned long ) data, cnt);return -EIO ; } }
@@ -123,7 +123,7 @@ snd_wavefront_fx_detect (snd_wavefront_t*/ if (inb (dev->fx_status) &0x80 ) { -snd_printk ("Hmm, probably a Maui or Tropez.\n" ); +dev_err (dev->card->dev,"Hmm, probably a Maui or Tropez.\n" );return -1 ; }
@@ -180,15 +180,15 @@ snd_wavefront_fx_ioctl (struct snd_hwdepcase WFFX_MEMSET :if (r.data[2 ] <=0 ) { -snd_printk ("cannot write " -"<= 0 bytes to FX\n" ); +dev_err (dev->card->dev, +"cannot write <= 0 bytes to FX\n" );return -EIO ; }else if (r.data[2 ] ==1 ) { pd = (unsigned short *) &r.data[3 ]; }else {if (r.data[2 ] >256 ) { -snd_printk ("cannot write " -"> 512 bytes to FX\n" ); +dev_err (dev->card->dev, +"cannot write > 512 bytes to FX\n" );return -EIO ; } page_data = memdup_user((unsigned char __user *)
@@ -208,8 +208,8 @@ snd_wavefront_fx_ioctl (struct snd_hwdepbreak ;default : -snd_printk ("FX: ioctl %d not yet supported\n" , - r.request); +dev_err (dev->card->dev,"FX: ioctl %d not yet supported\n" , + r.request);return -ENOTTY ; }return err;
@@ -254,8 +254,8 @@ snd_wavefront_fx_start (snd_wavefront_t goto out; } }else { -snd_printk (KERN_ERR "invalid address" -" in register data\n" ); +dev_err (dev->card->dev, +"invalid address in register data\n" ); err =-1 ; goto out; }
sound/isa/wavefront/wavefront_midi.c +10 -5
@@ -501,7 +501,8 @@ snd_wavefront_midi_start (snd_wavefront_for (i =0 ; i <30000 && !output_ready (midi); i++);if (!output_ready (midi)) { -snd_printk ("MIDI interface not ready for command\n" ); +dev_err (card->wavefront.card->dev, +"MIDI interface not ready for command\n" );return -1 ; }
@@ -523,7 +524,8 @@ snd_wavefront_midi_start (snd_wavefront_ }if (!ok) { -snd_printk ("cannot set UART mode for MIDI interface" ); +dev_err (card->wavefront.card->dev, +"cannot set UART mode for MIDI interface" ); dev->interrupts_are_midi =0 ;return -1 ; }
@@ -531,7 +533,8 @@ snd_wavefront_midi_start (snd_wavefront_/* Route external MIDI to WaveFront synth (by default) */ if (snd_wavefront_cmd (dev,WFC_MISYNTH_ON , rbuf, wbuf)) { -snd_printk ("can't enable MIDI-IN-2-synth routing.\n" ); +dev_warn (card->wavefront.card->dev, +"can't enable MIDI-IN-2-synth routing.\n" );/* XXX error ? */ }
@@ -547,14 +550,16 @@ snd_wavefront_midi_start (snd_wavefront_*/ if (snd_wavefront_cmd (dev,WFC_VMIDI_OFF , rbuf, wbuf)) { -snd_printk ("virtual MIDI mode not disabled\n" ); +dev_warn (card->wavefront.card->dev, +"virtual MIDI mode not disabled\n" );return 0 ;/* We're OK, but missing the external MIDI dev */ }snd_wavefront_midi_enable_virtual (card);if (snd_wavefront_cmd (dev,WFC_VMIDI_ON , rbuf, wbuf)) { -snd_printk ("cannot enable virtual MIDI mode.\n" ); +dev_warn (card->wavefront.card->dev, +"cannot enable virtual MIDI mode.\n" );snd_wavefront_midi_disable_virtual (card); }return 0 ;
sound/isa/wavefront/wavefront_synth.c +99 -97
561 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 631/737 ALSA: wavefront: Fix integer overflow in sample size validation
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Junrui Luo <[email protected]>
[ Upstream commit 0c4a13ba88594fd4a27292853e736c6b4349823d ]
The wavefront_send_sample() function has an integer overflow issue when validating sample size. The header->size field is u32 but gets cast to int for comparison with dev->freemem
Fix by using unsigned comparison to avoid integer overflow.
--- sound/isa/wavefront/wavefront_synth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
sound/isa/wavefront/wavefront_synth.c +2 -2
@@ -950,9 +950,9 @@ wavefront_send_sample (snd_wavefront_t *if (header->size) { dev->freemem =wavefront_freemem (dev); -if (dev->freemem < (int )header->size) { +if (dev->freemem <0 || dev->freemem < header->size) {dev_err (dev->card->dev, -"insufficient memory to load %d byte sample.\n" , +"insufficient memory to load %u byte sample.\n" , header->size);return -ENOMEM ; }
Greg Kroah-Hartman
maintainerPATCH 632/737 ALSA: wavefront: Use guard() for spin locks
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
[ Upstream commit 4b97f8e614ba46a50bd181d40b5a1424411a211a ]
Clean up the code using guard() for spin locks.
Merely code refactoring, and no behavior change.
Stable-dep-of: e11c5c13ce0a ("ALSA: wavefront: Clear substream pointers on close")
--- sound/isa/wavefront/wavefront_midi.c | 127 +++++++++++++--------------------- sound/isa/wavefront/wavefront_synth.c | 18 ++-- 2 files changed, 59 insertions(+), 86 deletions(-)
sound/isa/wavefront/wavefront_midi.c +50 -77
@@ -113,7 +113,6 @@ static void snd_wavefront_midi_output_wr {snd_wavefront_midi_t *midi = &card->wavefront.midi;snd_wavefront_mpu_id mpu; -unsigned long flags;unsigned char midi_byte;int max =256 , mask =1 ;int timeout;
@@ -142,11 +141,9 @@ static void snd_wavefront_midi_output_wrbreak ; } -spin_lock_irqsave (&midi->virtual, flags); -if ((midi->mode[midi->output_mpu] &MPU401_MODE_OUTPUT ) ==0 ) { -spin_unlock_irqrestore (&midi->virtual, flags); +guard (spinlock_irqsave)(&midi->virtual); +if ((midi->mode[midi->output_mpu] &MPU401_MODE_OUTPUT ) ==0 ) goto __second; - }if (output_ready (midi)) {if (snd_rawmidi_transmit (midi->substream_output[midi->output_mpu], &midi_byte,1 ) ==1 ) { if (!midi->isvirtual ||
@@ -160,14 +157,11 @@ static void snd_wavefront_midi_output_wrdel_timer (&midi->timer); } midi->mode[midi->output_mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER ; -spin_unlock_irqrestore (&midi->virtual, flags); goto __second; } }else { -spin_unlock_irqrestore (&midi->virtual, flags);return ; } -spin_unlock_irqrestore (&midi->virtual, flags); } __second:
@@ -185,15 +179,13 @@ static void snd_wavefront_midi_output_wrbreak ; } -spin_lock_irqsave (&midi->virtual, flags); +guard (spinlock_irqsave)(&midi->virtual);if (!midi->isvirtual) mask =0 ; mpu = midi->output_mpu ^ mask; mask =0 ;/* don't invert the value from now */ -if ((midi->mode[mpu] &MPU401_MODE_OUTPUT ) ==0 ) { -spin_unlock_irqrestore (&midi->virtual, flags); +if ((midi->mode[mpu] &MPU401_MODE_OUTPUT ) ==0 )return ; - }if (snd_rawmidi_transmit_empty (midi->substream_output[mpu])) goto __timer;if (output_ready (midi)) {
@@ -215,20 +207,16 @@ static void snd_wavefront_midi_output_wrdel_timer (&midi->timer); } midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER ; -spin_unlock_irqrestore (&midi->virtual, flags);return ; } }else { -spin_unlock_irqrestore (&midi->virtual, flags);return ; } -spin_unlock_irqrestore (&midi->virtual, flags); } }static int snd_wavefront_midi_input_open (struct snd_rawmidi_substream *substream) { -unsigned long flags;snd_wavefront_midi_t *midi;snd_wavefront_mpu_id mpu;
@@ -243,17 +231,15 @@ static int snd_wavefront_midi_input_openif (!midi)return -EIO ; -spin_lock_irqsave (&midi->open, flags); +guard (spinlock_irqsave)(&midi->open); midi->mode[mpu] |=MPU401_MODE_INPUT ; midi->substream_input[mpu] = substream; -spin_unlock_irqrestore (&midi->open, flags);return 0 ; }static int snd_wavefront_midi_output_open (struct snd_rawmidi_substream *substream) { -unsigned long flags;snd_wavefront_midi_t *midi;snd_wavefront_mpu_id mpu;
@@ -268,17 +254,15 @@ static int snd_wavefront_midi_output_opeif (!midi)return -EIO ; -spin_lock_irqsave (&midi->open, flags); +guard (spinlock_irqsave)(&midi->open); midi->mode[mpu] |=MPU401_MODE_OUTPUT ; midi->substream_output[mpu] = substream; -spin_unlock_irqrestore (&midi->open, flags);return 0 ; }static int snd_wavefront_midi_input_close (struct snd_rawmidi_substream *substream) { -unsigned long flags;snd_wavefront_midi_t *midi;snd_wavefront_mpu_id mpu;
@@ -293,16 +277,14 @@ static int snd_wavefront_midi_input_closif (!midi)return -EIO ; -spin_lock_irqsave (&midi->open, flags); +guard (spinlock_irqsave)(&midi->open); midi->mode[mpu] &= ~MPU401_MODE_INPUT ; -spin_unlock_irqrestore (&midi->open, flags);return 0 ; }static int snd_wavefront_midi_output_close (struct snd_rawmidi_substream *substream) { -unsigned long flags;snd_wavefront_midi_t *midi;snd_wavefront_mpu_id mpu;
@@ -317,15 +299,13 @@ static int snd_wavefront_midi_output_cloif (!midi)return -EIO ; -spin_lock_irqsave (&midi->open, flags); +guard (spinlock_irqsave)(&midi->open); midi->mode[mpu] &= ~MPU401_MODE_OUTPUT ; -spin_unlock_irqrestore (&midi->open, flags);return 0 ; }static void snd_wavefront_midi_input_trigger (struct snd_rawmidi_substream *substream,int up) { -unsigned long flags;snd_wavefront_midi_t *midi;snd_wavefront_mpu_id mpu;
@@ -341,30 +321,27 @@ static void snd_wavefront_midi_input_triif (!midi)return ; -spin_lock_irqsave (&midi->virtual, flags); +guard (spinlock_irqsave)(&midi->virtual);if (up) { midi->mode[mpu] |=MPU401_MODE_INPUT_TRIGGER ; }else { midi->mode[mpu] &= ~MPU401_MODE_INPUT_TRIGGER ; } -spin_unlock_irqrestore (&midi->virtual, flags); }static void snd_wavefront_midi_output_timer (struct timer_list *t) {snd_wavefront_midi_t *midi =from_timer (midi, t, timer);snd_wavefront_card_t *card = midi->timer_card; -unsigned long flags; -spin_lock_irqsave (&midi->virtual, flags); -mod_timer (&midi->timer,1 + jiffies); -spin_unlock_irqrestore (&midi->virtual, flags); + scoped_guard(spinlock_irqsave, &midi->virtual) { +mod_timer (&midi->timer,1 + jiffies); + }snd_wavefront_midi_output_write (card); }static void snd_wavefront_midi_output_trigger (struct snd_rawmidi_substream *substream,int up) { -unsigned long flags;snd_wavefront_midi_t *midi;snd_wavefront_mpu_id mpu;
@@ -380,22 +357,22 @@ static void snd_wavefront_midi_output_trif (!midi)return ; -spin_lock_irqsave (&midi->virtual, flags); -if (up) { -if ((midi->mode[mpu] &MPU401_MODE_OUTPUT_TRIGGER ) ==0 ) { -if (!midi->istimer) { -timer_setup (&midi->timer, - snd_wavefront_midi_output_timer, -0 ); -mod_timer (&midi->timer,1 + jiffies); + scoped_guard(spinlock_irqsave, &midi->virtual) { +if (up) { +if ((midi->mode[mpu] &MPU401_MODE_OUTPUT_TRIGGER ) ==0 ) { +if (!midi->istimer) { +timer_setup (&midi->timer, + snd_wavefront_midi_output_timer, +0 ); +mod_timer (&midi->timer,1 + jiffies); + } + midi->istimer++; + midi->mode[mpu] |=MPU401_MODE_OUTPUT_TRIGGER ; } - midi->istimer++; - midi->mode[mpu] |=MPU401_MODE_OUTPUT_TRIGGER ; + }else { + midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER ; } - }else { - midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER ; } -spin_unlock_irqrestore (&midi->virtual, flags);if (up)snd_wavefront_midi_output_write ((snd_wavefront_card_t *)substream->rmidi->card->private_data);
@@ -405,7 +382,6 @@ void snd_wavefront_midi_interrupt (snd_wavefront_card_t *card) { -unsigned long flags;snd_wavefront_midi_t *midi;static struct snd_rawmidi_substream *substream =NULL ;static int mpu = external_mpu;
@@ -419,37 +395,37 @@ snd_wavefront_midi_interrupt (snd_wavefrreturn ; } -spin_lock_irqsave (&midi->virtual, flags); -while (--max) { + scoped_guard(spinlock_irqsave, &midi->virtual) { +while (--max) { -if (input_avail (midi)) { - byte =read_data (midi); +if (input_avail (midi)) { + byte =read_data (midi); -if (midi->isvirtual) { -if (byte ==WF_EXTERNAL_SWITCH ) { - substream = midi->substream_input[external_mpu]; - mpu = external_mpu; - }else if (byte ==WF_INTERNAL_SWITCH ) { - substream = midi->substream_output[internal_mpu]; +if (midi->isvirtual) { +if (byte ==WF_EXTERNAL_SWITCH ) { + substream = midi->substream_input[external_mpu]; + mpu = external_mpu; + }else if (byte ==WF_INTERNAL_SWITCH ) { + substream = midi->substream_output[internal_mpu]; + mpu = internal_mpu; + }/* else just leave it as it is */ + }else { + substream = midi->substream_input[internal_mpu]; mpu = internal_mpu; - }/* else just leave it as it is */ - }else { - substream = midi->substream_input[internal_mpu]; - mpu = internal_mpu; - } + } -if (substream ==NULL ) { -continue ; - } +if (substream ==NULL ) { +continue ; + } -if (midi->mode[mpu] &MPU401_MODE_INPUT_TRIGGER ) { -snd_rawmidi_receive (substream, &byte,1 ); +if (midi->mode[mpu] &MPU401_MODE_INPUT_TRIGGER ) { +snd_rawmidi_receive (substream, &byte,1 ); + } + }else { +break ; } - }else { -break ; } - } -spin_unlock_irqrestore (&midi->virtual, flags); + }snd_wavefront_midi_output_write (card); }
@@ -471,13 +447,10 @@ void snd_wavefront_midi_disable_virtual (snd_wavefront_card_t *card) { -unsigned long flags; - -spin_lock_irqsave (&card->wavefront.midi.virtual, flags); +guard (spinlock_irqsave)(&card->wavefront.midi.virtual);// snd_wavefront_midi_input_close (card->ics2115_external_rmidi); // snd_wavefront_midi_output_close (card->ics2115_external_rmidi); card->wavefront.midi.isvirtual =0 ; -spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags); }int
sound/isa/wavefront/wavefront_synth.c +9 -9
@@ -1741,10 +1741,10 @@ snd_wavefront_internal_interrupt (snd_wareturn ; } -spin_lock (&dev->irq_lock); - dev->irq_ok =1 ; - dev->irq_cnt++; -spin_unlock (&dev->irq_lock); + scoped_guard(spinlock, &dev->irq_lock) { + dev->irq_ok =1 ; + dev->irq_cnt++; + }wake_up (&dev->interrupt_sleeper); }
@@ -1796,11 +1796,11 @@ wavefront_should_cause_interrupt (snd_wawait_queue_entry_t wait;init_waitqueue_entry (&wait, current); -spin_lock_irq (&dev->irq_lock); -add_wait_queue (&dev->interrupt_sleeper, &wait); - dev->irq_ok =0 ; -outb (val,port); -spin_unlock_irq (&dev->irq_lock); + scoped_guard(spinlock_irq, &dev->irq_lock) { +add_wait_queue (&dev->interrupt_sleeper, &wait); + dev->irq_ok =0 ; +outb (val, port); + }while (!dev->irq_ok &&time_before (jiffies, timeout)) {schedule_timeout_uninterruptible (1 );barrier ();
Greg Kroah-Hartman
maintainerPATCH 633/737 ALSA: wavefront: Clear substream pointers on close
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Junrui Luo <[email protected]>
[ Upstream commit e11c5c13ce0ab2325d38fe63500be1dd88b81e38 ]
Clear substream pointers in close functions to avoid leaving dangling pointers, helping to improve code safety and
prevents potential issues.
--- sound/isa/wavefront/wavefront_midi.c | 2 ++ 1 file changed, 2 insertions(+)
sound/isa/wavefront/wavefront_midi.c +2 -0
@@ -278,6 +278,7 @@ static int snd_wavefront_midi_input_closreturn -EIO ;guard (spinlock_irqsave)(&midi->open); + midi->substream_input[mpu] =NULL ; midi->mode[mpu] &= ~MPU401_MODE_INPUT ;return 0 ;
@@ -300,6 +301,7 @@ static int snd_wavefront_midi_output_cloreturn -EIO ;guard (spinlock_irqsave)(&midi->open); + midi->substream_output[mpu] =NULL ; midi->mode[mpu] &= ~MPU401_MODE_OUTPUT ;return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 634/737 ALSA: hda: cs35l41: Fix NULL pointer dereference in cs35l41_hda_read_acpi()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Denis Arefev <[email protected]>
[ Upstream commit c34b04cc6178f33c08331568c7fd25c5b9a39f66 ]
The acpi_get_first_physical_node() function can return NULL, in which case the get_device() function also returns NULL, but this value is then dereferenced without checking,so add a check to prevent a crash.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- sound/pci/hda/cs35l41_hda.c | 2 ++ 1 file changed, 2 insertions(+)
sound/pci/hda/cs35l41_hda.c +2 -0
@@ -1432,6 +1432,8 @@ static int cs35l41_hda_read_acpi(struct physdev =get_device (acpi_get_first_physical_node (adev));acpi_dev_put (adev); +if (!physdev) +return -ENODEV ; sub =acpi_get_subsystem_id (ACPI_HANDLE (physdev));if (IS_ERR (sub))
Greg Kroah-Hartman
maintainerPATCH 635/737 ext4: fix string copying in parse_apply_sb_mount_options()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fedor Pchelkin <[email protected]>
[ Upstream commit ee5a977b4e771cc181f39d504426dbd31ed701cc ]
strscpy_pad() can't be used to copy a non-NUL-term string into a NUL-term string of possibly bigger size. Commit 0efc5990bca5 ("string.h: Introduce memtostr() and memtostr_pad()") provides additional information in that regard. So if this happens, the following warning is observed:
strnlen: detected buffer overflow: 65 byte read of buffer size 64
WARNING: CPU: 0 PID: 28655 at lib/string_helpers.c:1032 __fortify_report+0x96/0xc0 lib/string_helpers.c:1032 Modules linked in: CPU: 0 UID: 0 PID: 28655 Comm: syz-executor.3 Not tainted 6.12.54-syzkaller-00144-g5f0270f1ba00 #0 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 RIP: 0010:__fortify_report+0x96/0xc0 lib/string_helpers.c:1032 Call Trace: <TASK> __fortify_panic+0x1f/0x30 lib/string_helpers.c:1039 strnlen include/linux/fortify-string.h:235 [inline] sized_strscpy include/linux/fortify-string.h:309 [inline] parse_apply_sb_mount_options fs/ext4/super.c:2504 [inline] __ext4_fill_super fs/ext4/super.c:5261 [inline] ext4_fill_super+0x3c35/0xad00 fs/ext4/super.c:5706 get_tree_bdev_flags+0x387/0x620 fs/super.c:1636 vfs_get_tree+0x93/0x380 fs/super.c:1814 do_new_mount fs/namespace.c:3553 [inline] path_mount+0x6ae/0x1f70 fs/namespace.c:3880 do_mount fs/namespace.c:3893 [inline] __do_sys_mount fs/namespace.c:4103 [inline] __se_sys_mount fs/namespace.c:4080 [inline] __x64_sys_mount+0x280/0x300 fs/namespace.c:4080 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0x64/0x140 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x76/0x7e
Since userspace is expected to provide s_mount_opts field to be at most 63 characters long with the ending byte being NUL-term, use a 64-byte buffer which matches the size of s_mount_opts, so that strscpy_pad() does its job properly. Return with error if the user still managed to provide a non-NUL-term string here.
Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
Message-ID: <[email protected]>
--- fs/ext4/super.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
fs/ext4/super.c +3 -2
@@ -2507,7 +2507,7 @@ static int parse_apply_sb_mount_options( struct ext4_fs_context *m_ctx) {struct ext4_sb_info *sbi =EXT4_SB (sb); -char s_mount_opts[65 ]; +char s_mount_opts[64 ];struct ext4_fs_context *s_ctx =NULL ;struct fs_context *fc =NULL ;int ret = -ENOMEM ;
@@ -2515,7 +2515,8 @@ static int parse_apply_sb_mount_options(if (!sbi->s_es->s_mount_opts[0 ])return 0 ; -strscpy_pad (s_mount_opts, sbi->s_es->s_mount_opts,sizeof (s_mount_opts)); +if (strscpy_pad (s_mount_opts, sbi->s_es->s_mount_opts,sizeof (s_mount_opts)) <0 ) +return -E2BIG ; fc =kzalloc (sizeof (struct fs_context ),GFP_KERNEL );if (!fc)
Greg Kroah-Hartman
maintainerPATCH 636/737 jbd2: fix the inconsistency between checksum and data in memory for journal sb
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ye Bin <[email protected]>
[ Upstream commit 6abfe107894af7e8ce3a2e120c619d81ee764ad5 ]
Copying the file system while it is mounted as read-only results in a mount failure:
[~]# mkfs.ext4 -F /dev/sdc
[~]# mount /dev/sdc -o ro /mnt/test
[~]# dd if=/dev/sdc of=/dev/sda bs=1M
[~]# mount /dev/sda /mnt/test1
[ 1094.849826] JBD2: journal checksum error [ 1094.850927] EXT4-fs (sda): Could not load journal inode
mount: mount /dev/sda on /mnt/test1 failed: Bad message
The process described above is just an abstracted way I came up with to reproduce the issue. In the actual scenario, the file system was mounted read-only and then copied while it was still mounted. It was found that the mount operation failed. The user intended to verify the data or use it as a backup, and this action was performed during a version upgrade. Above issue may happen as follows:ext4_fill_super
set_journal_csum_feature_set(sb)
if (ext4_has_metadata_csum(sb))
incompat = JBD2_FEATURE_INCOMPAT_CSUM_V3;
if (test_opt(sb, JOURNAL_CHECKSUM)
jbd2_journal_set_features(sbi->s_journal, compat, 0, incompat);
lock_buffer(journal->j_sb_buffer);
sb->s_feature_incompat |= cpu_to_be32(incompat);
//The data in the journal sb was modified, but the checksum was not
updated, so the data remaining in memory has a mismatch between the
data and the checksum.
unlock_buffer(journal->j_sb_buffer);In this case, the journal sb copied over is in a state where the checksum and data are inconsistent, so mounting fails.
To solve the above issue, update the checksum in memory after modifying the journal sb.
Message-ID: <[email protected]>
--- fs/jbd2/journal.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
fs/jbd2/journal.c +14 -0
@@ -2405,6 +2405,12 @@ int jbd2_journal_set_features(journal_t sb->s_feature_compat |=cpu_to_be32 (compat); sb->s_feature_ro_compat |=cpu_to_be32 (ro); sb->s_feature_incompat |=cpu_to_be32 (incompat); +/* +* Update the checksum now so that it is valid even for read-only +* filesystems where jbd2_write_superblock() doesn't get called. +*/ +if (jbd2_journal_has_csum_v2or3 (journal)) + sb->s_checksum =jbd2_superblock_csum (journal, sb);unlock_buffer (journal->j_sb_buffer);jbd2_journal_init_transaction_limits (journal);
@@ -2434,9 +2440,17 @@ void jbd2_journal_clear_features(journal sb = journal->j_superblock; +lock_buffer (journal->j_sb_buffer); sb->s_feature_compat &= ~cpu_to_be32 (compat); sb->s_feature_ro_compat &= ~cpu_to_be32 (ro); sb->s_feature_incompat &= ~cpu_to_be32 (incompat); +/* +* Update the checksum now so that it is valid even for read-only +* filesystems where jbd2_write_superblock() doesn't get called. +*/ +if (jbd2_journal_has_csum_v2or3 (journal)) + sb->s_checksum =jbd2_superblock_csum (journal, sb); +unlock_buffer (journal->j_sb_buffer);jbd2_journal_init_transaction_limits (journal); }EXPORT_SYMBOL (jbd2_journal_clear_features);
Greg Kroah-Hartman
maintainerPATCH 637/737 gfs2: fix freeze error handling
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexey Velichayshiy <[email protected]>
[ Upstream commit 4cfc7d5a4a01d2133b278cdbb1371fba1b419174 ]
After commit b77b4a4815a9 ("gfs2: Rework freeze / thaw logic"), the freeze error handling is broken because gfs2_do_thaw() overwrites the 'error' variable, causing incorrect processing of the original freeze error.
Fix this by calling gfs2_do_thaw() when gfs2_lock_fs_check_clean() fails but ignoring its return value to preserve the original freeze error for proper reporting.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- fs/gfs2/super.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
fs/gfs2/super.c +1 -3
@@ -776,9 +776,7 @@ static int gfs2_freeze_super(struct supeif (!error)break ;/* success */ - error =gfs2_do_thaw (sdp); -if (error) - goto out; + (void )gfs2_do_thaw (sdp);if (error == -EBUSY )fs_err (sdp,"waiting for recovery before freeze\n" );
Greg Kroah-Hartman
maintainerPATCH 638/737 btrfs: dont rewrite ret from inode_permission
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Josef Bacik <[email protected]>
[ Upstream commit 0185c2292c600993199bc6b1f342ad47a9e8c678 ]
In our user safe ino resolve ioctl we'll just turn any ret into -EACCES from inode_permission(). This is redundant, and could potentially be wrong if we had an ENOMEM in the security layer or some such other error, so simply return the actual return value.
Note: The patch was taken from v5 of fscrypt patchset
(https://lore.kernel.org/linux-btrfs/[email protected]/)
which was handled over time by various people: Omar Sandoval, Sweet Tea Dorminy, Josef Bacik.
--- fs/btrfs/ioctl.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
fs/btrfs/ioctl.c +1 -3
@@ -2006,10 +2006,8 @@ static int btrfs_search_path_in_tree_use ret =inode_permission (idmap, temp_inode,MAY_READ |MAY_EXEC );iput (temp_inode); -if (ret) { - ret = -EACCES ; +if (ret) goto out_put; - }if (key.offset == upper_limit.objectid)break ;
Greg Kroah-Hartman
maintainerPATCH 639/737 wifi: mt76: Fix DTS power-limits on little endian systems
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: "Sven Eckelmann (Plasma Cloud)" <[email protected]>
[ Upstream commit 38b845e1f9e810869b0a0b69f202b877b7b7fb12 ]
The power-limits for ru and mcs and stored in the devicetree as bytewise array (often with sizes which are not a multiple of 4). These arrays have a prefix which defines for how many modes a line is applied. This prefix is also only a byte - but the code still tried to fix the endianness of this byte with a be32 operation. As result, loading was mostly failing or was sending completely unexpected values to the firmware.
Since the other rates are also stored in the devicetree as bytewise arrays, just drop the u32 access + be32_to_cpu conversion and directly access them as bytes arrays.
--- drivers/net/wireless/mediatek/mt76/eeprom.c | 37 ++++++++++++++++++---------- 1 file changed, 24 insertions(+), 13 deletions(-)
drivers/net/wireless/mediatek/mt76/eeprom.c +24 -13
@@ -245,6 +245,19 @@ mt76_get_of_array(struct device_node *npreturn prop->value; } +static const s8 * +mt76_get_of_array_s8 (struct device_node *np,char *name,size_t *len,int min) +{ +struct property *prop =of_find_property (np, name,NULL ); + +if (!prop || !prop->value || prop->length < min) +return NULL ; + + *len = prop->length; + +return prop->value; +} +static struct device_node *mt76_find_channel_node (struct device_node *np,struct ieee80211_channel *chan) {
@@ -284,7 +297,7 @@ mt76_get_txs_delta(struct device_node *n }static void -mt76_apply_array_limit (s8 *pwr,size_t pwr_len,const __be32 *data, +mt76_apply_array_limit (s8 *pwr,size_t pwr_len,const s8 *data,s8 target_power,s8 nss_delta,s8 *max_power) {int i;
@@ -293,15 +306,14 @@ mt76_apply_array_limit(s8 *pwr, size_t preturn ;for (i =0 ; i < pwr_len; i++) { - pwr[i] =min_t (s8, target_power, -be32_to_cpu (data[i]) + nss_delta); + pwr[i] =min_t (s8, target_power, data[i] + nss_delta); *max_power =max (*max_power, pwr[i]); } }static void mt76_apply_multi_array_limit (s8 *pwr,size_t pwr_len,s8 pwr_num, -const __be32 *data,size_t len,s8 target_power, +const s8 *data,size_t len,s8 target_power,s8 nss_delta,s8 *max_power) {int i, cur;
@@ -309,8 +321,7 @@ mt76_apply_multi_array_limit(s8 *pwr, siif (!data)return ; - len /=4 ; - cur =be32_to_cpu (data[0 ]); + cur = data[0 ];for (i =0 ; i < pwr_num; i++) {if (len < pwr_len +1 )break ;
@@ -325,7 +336,7 @@ mt76_apply_multi_array_limit(s8 *pwr, siif (!len)break ; - cur =be32_to_cpu (data[0 ]); + cur = data[0 ]; } }
@@ -336,7 +347,7 @@ s8 mt76_get_rate_power_limits(struct mt7 {struct mt76_dev *dev = phy->dev;struct device_node *np; -const __be32 *val; +const s8 *val;char name[16 ];u32 mcs_rates = dev->drv->mcs_rates;u32 ru_rates =ARRAY_SIZE (dest->ru[0 ]);
@@ -382,21 +393,21 @@ s8 mt76_get_rate_power_limits(struct mt7 txs_delta =mt76_get_txs_delta (np,hweight8 (phy->antenna_mask)); - val =mt76_get_of_array (np,"rates-cck" , &len,ARRAY_SIZE (dest->cck)); + val =mt76_get_of_array_s8 (np,"rates-cck" , &len,ARRAY_SIZE (dest->cck));mt76_apply_array_limit (dest->cck,ARRAY_SIZE (dest->cck), val, target_power, txs_delta, &max_power); - val =mt76_get_of_array (np,"rates-ofdm" , - &len,ARRAY_SIZE (dest->ofdm)); + val =mt76_get_of_array_s8 (np,"rates-ofdm" , + &len,ARRAY_SIZE (dest->ofdm));mt76_apply_array_limit (dest->ofdm,ARRAY_SIZE (dest->ofdm), val, target_power, txs_delta, &max_power); - val =mt76_get_of_array (np,"rates-mcs" , &len, mcs_rates +1 ); + val =mt76_get_of_array_s8 (np,"rates-mcs" , &len, mcs_rates +1 );mt76_apply_multi_array_limit (dest->mcs[0 ],ARRAY_SIZE (dest->mcs[0 ]),ARRAY_SIZE (dest->mcs), val, len, target_power, txs_delta, &max_power); - val =mt76_get_of_array (np,"rates-ru" , &len, ru_rates +1 ); + val =mt76_get_of_array_s8 (np,"rates-ru" , &len, ru_rates +1 );mt76_apply_multi_array_limit (dest->ru[0 ],ARRAY_SIZE (dest->ru[0 ]),ARRAY_SIZE (dest->ru), val, len, target_power, txs_delta, &max_power);
Greg Kroah-Hartman
maintainerPATCH 640/737 mm/ksm: fix exec/fork inheritance support for prctl
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: xu xin <[email protected]>
[ Upstream commit 590c03ca6a3fbb114396673314e2aa483839608b ]
Patch series "ksm: fix exec/fork inheritance", v2.
This series fixes exec/fork inheritance. See the detailed description of the issue below.
This patch (of 2):
Background
==========
commit d7597f59d1d33 ("mm: add new api to enable ksm per process") introduced MMF_VM_MERGE_ANY for mm->flags, and allowed user to set it by prctl() so that the process's VMAs are forcibly scanned by ksmd.
Subsequently, the 3c6f33b7273a ("mm/ksm: support fork/exec for prctl") supported inheriting the MMF_VM_MERGE_ANY flag when a task calls execve().
Finally, commit 3a9e567ca45fb ("mm/ksm: fix ksm exec support for prctl") fixed the issue that ksmd doesn't scan the mm_struct with MMF_VM_MERGE_ANY by adding the mm_slot to ksm_mm_head in __bprm_mm_init().
Problem
=======
In some extreme scenarios, however, this inheritance of MMF_VM_MERGE_ANY during exec/fork can fail. For example, when the scanning frequency of ksmd is tuned extremely high, a process carrying MMF_VM_MERGE_ANY may still fail to pass it to the newly exec'd process. This happens because ksm_execve() is executed too early in the do_execve flow (prematurely adding the new mm_struct to the ksm_mm_slot list).
As a result, before do_execve completes, ksmd may have already performed a scan and found that this new mm_struct has no VM_MERGEABLE VMAs, thus clearing its MMF_VM_MERGE_ANY flag. Consequently, when the new program executes, the flag MMF_VM_MERGE_ANY inheritance missed.
Root reason
===========
commit d7597f59d1d33 ("mm: add new api to enable ksm per process") clear the flag MMF_VM_MERGE_ANY when ksmd found no VM_MERGEABLE VMAs.
Solution
========
Firstly, Don't clear MMF_VM_MERGE_ANY when ksmd found no VM_MERGEABLE VMAs, because perhaps their mm_struct has just been added to ksm_mm_slot list, and its process has not yet officially started running or has not yet performed mmap/brk to allocate anonymous VMAS.
Secondly, recheck MMF_VM_MERGEABLE again if a process takes MMF_VM_MERGE_ANY, and create a mm_slot and join it into ksm_scan_list again.
--- mm/ksm.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-)
mm/ksm.c +16 -2
@@ -2451,8 +2451,14 @@ no_vmas:spin_unlock (&ksm_mmlist_lock);mm_slot_free (mm_slot_cache, mm_slot); +/* +* Only clear MMF_VM_MERGEABLE. We must not clear +* MMF_VM_MERGE_ANY, because for those MMF_VM_MERGE_ANY process, +* perhaps their mm_struct has just been added to ksm_mm_slot +* list, and its process has not yet officially started running +* or has not yet performed mmap/brk to allocate anonymous VMAS. +*/ clear_bit (MMF_VM_MERGEABLE , &mm->flags); -clear_bit (MMF_VM_MERGE_ANY , &mm->flags);mmap_read_unlock (mm);mmdrop (mm); }else {
@@ -2567,8 +2573,16 @@ void ksm_add_vma(struct vm_area_struct * {struct mm_struct *mm = vma->vm_mm; -if (test_bit (MMF_VM_MERGE_ANY , &mm->flags)) +if (test_bit (MMF_VM_MERGE_ANY , &mm->flags)) {__ksm_add_vma (vma); +/* +* Generally, the flags here always include MMF_VM_MERGEABLE. +* However, in rare cases, this flag may be cleared by ksmd who +* scans a cycle without finding any mergeable vma. +*/ +if (unlikely (!test_bit (MMF_VM_MERGEABLE , &mm->flags))) +__ksm_enter (mm); + } }static void ksm_add_vmas (struct mm_struct *mm)
Greg Kroah-Hartman
maintainerPATCH 641/737 usb: ohci-nxp: Use helper function devm_clk_get_enabled()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Zekun <[email protected]>
[ Upstream commit c146ede472717f352b7283a525bd9a1a2b15e2cf ]
devm_clk_get() and clk_prepare_enable() can be replaced by helper function devm_clk_get_enabled(). Let's use devm_clk_get_enabled() to simplify code and avoid calling clk_disable_unprepare().
Stable-dep-of: b4c61e542faf ("usb: ohci-nxp: fix device leak on probe failure")
--- drivers/usb/host/ohci-nxp.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-)
drivers/usb/host/ohci-nxp.c +4 -14
@@ -51,8 +51,6 @@ static struct hc_driver __read_mostly ohstatic struct i2c_client *isp1301_i2c_client; -static struct clk *usb_host_clk; -static void isp1301_configure_lpc32xx (void ) {/* LPC32XX only supports DAT_SE0 USB mode */
@@ -155,6 +153,7 @@ static int ohci_hcd_nxp_probe(struct plastruct resource *res;int ret =0 , irq;struct device_node *isp1301_node; +struct clk *usb_host_clk;if (pdev->dev.of_node) { isp1301_node = of_parse_phandle(pdev->dev.of_node,
@@ -180,26 +179,20 @@ static int ohci_hcd_nxp_probe(struct pla }/* Enable USB host clock */ - usb_host_clk =devm_clk_get (&pdev->dev,NULL ); + usb_host_clk =devm_clk_get_enabled (&pdev->dev,NULL );if (IS_ERR (usb_host_clk)) { -dev_err (&pdev->dev,"failed to acquire USB OHCI clock\n" ); +dev_err (&pdev->dev,"failed to acquire and start USB OHCI clock\n" ); ret =PTR_ERR (usb_host_clk); goto fail_disable; } - ret =clk_prepare_enable (usb_host_clk); -if (ret <0 ) { -dev_err (&pdev->dev,"failed to start USB OHCI clock\n" ); - goto fail_disable; - } -isp1301_configure (); hcd =usb_create_hcd (driver, &pdev->dev,dev_name (&pdev->dev));if (!hcd) {dev_err (&pdev->dev,"Failed to allocate HC buffer\n" ); ret = -ENOMEM ; - goto fail_hcd; + goto fail_disable; } hcd->regs =devm_platform_get_and_ioremap_resource (pdev,0 , &res);
@@ -229,8 +222,6 @@ static int ohci_hcd_nxp_probe(struct plaohci_nxp_stop_hc (); fail_resource:usb_put_hcd (hcd); -fail_hcd: -clk_disable_unprepare (usb_host_clk); fail_disable: isp1301_i2c_client =NULL ;return ret;
@@ -243,7 +234,6 @@ static void ohci_hcd_nxp_remove(struct pusb_remove_hcd (hcd);ohci_nxp_stop_hc ();usb_put_hcd (hcd); -clk_disable_unprepare (usb_host_clk); isp1301_i2c_client =NULL ; }
Greg Kroah-Hartman
maintainerPATCH 642/737 usb: ohci-nxp: fix device leak on probe failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
[ Upstream commit b4c61e542faf8c9131d69ecfc3ad6de96d1b2ab8 ]
Make sure to drop the reference taken when looking up the PHY I2C device during probe on probe failure (e.g. probe deferral) and on driver unbind.
--- drivers/usb/host/ohci-nxp.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/usb/host/ohci-nxp.c +2 -0
@@ -223,6 +223,7 @@ static int ohci_hcd_nxp_probe(struct pla fail_resource:usb_put_hcd (hcd); fail_disable: +put_device (&isp1301_i2c_client->dev); isp1301_i2c_client =NULL ;return ret; }
@@ -234,6 +235,7 @@ static void ohci_hcd_nxp_remove(struct pusb_remove_hcd (hcd);ohci_nxp_stop_hc ();usb_put_hcd (hcd); +put_device (&isp1301_i2c_client->dev); isp1301_i2c_client =NULL ; }
Greg Kroah-Hartman
maintainerPATCH 643/737 scsi: ufs: core: Add ufshcd_update_evt_hist() for UFS suspend error
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Seunghwan Baek <[email protected]>
[ Upstream commit c9f36f04a8a2725172cdf2b5e32363e4addcb14c ]
If UFS resume fails, the event history is updated in ufshcd_resume(), but there is no code anywhere to record UFS suspend. Therefore, add code to record UFS suspend error event history.
--- drivers/ufs/core/ufshcd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/ufs/core/ufshcd.c +4 -1
@@ -10182,7 +10182,7 @@ static int ufshcd_suspend(struct ufs_hba ret =ufshcd_setup_clocks (hba, false);if (ret) {ufshcd_enable_irq (hba); -return ret; + goto out; }if (ufshcd_is_clkgating_allowed (hba)) { hba->clk_gating.state =CLKS_OFF ;
@@ -10193,6 +10193,9 @@ static int ufshcd_suspend(struct ufs_hbaufshcd_vreg_set_lpm (hba);/* Put the host controller in low power mode if possible */ ufshcd_hba_vreg_set_lpm (hba); +out: +if (ret) +ufshcd_update_evt_hist (hba,UFS_EVT_SUSPEND_ERR , (u32 )ret);return ret; }
Greg Kroah-Hartman
maintainerPATCH 644/737 mptcp: pm: ignore unknown endpoint flags
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: "Matthieu Baerts (NGI0)" <[email protected]>
[ Upstream commit 0ace3297a7301911e52d8195cb1006414897c859 ]
Before this patch, the kernel was saving any flags set by the userspace, even unknown ones. This doesn't cause critical issues because the kernel is only looking at specific ones. But on the other hand, endpoints dumps could tell the userspace some recent flags seem to be supported on older kernel versions.
Instead, ignore all unknown flags when parsing them. By doing that, the userspace can continue to set unsupported flags, but it has a way to verify what is supported by the kernel.
Note that it sounds better to continue accepting unsupported flags not to change the behaviour, but also that eases things on the userspace side by adding "optional" endpoint types only supported by newer kernel versions without having to deal with the different kernel versions.
A note for the backports: there will be conflicts in mptcp.h on older versions not having the mentioned flags, the new line should still be added last, and the '5' needs to be adapted to have the same value as the last entry.
--- include/uapi/linux/mptcp.h | 1 + net/mptcp/pm_netlink.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-)
include/uapi/linux/mptcp.h +1 -0
@@ -88,6 +88,7 @@ enum {#define MPTCP_PM_ADDR_FLAG_BACKUP (1 << 2)#define MPTCP_PM_ADDR_FLAG_FULLMESH (1 << 3)#define MPTCP_PM_ADDR_FLAG_IMPLICIT (1 << 4) +#define MPTCP_PM_ADDR_FLAGS_MASK GENMASK(4, 0)enum {MPTCP_PM_CMD_UNSPEC ,
net/mptcp/pm_netlink.c +2 -1
@@ -1435,7 +1435,8 @@ int mptcp_pm_parse_entry(struct nlattr * }if (tb[MPTCP_PM_ADDR_ATTR_FLAGS ]) - entry->flags =nla_get_u32 (tb[MPTCP_PM_ADDR_ATTR_FLAGS ]); + entry->flags =nla_get_u32 (tb[MPTCP_PM_ADDR_ATTR_FLAGS ]) & +MPTCP_PM_ADDR_FLAGS_MASK ;if (tb[MPTCP_PM_ADDR_ATTR_PORT ]) entry->addr.port =htons (nla_get_u16 (tb[MPTCP_PM_ADDR_ATTR_PORT ]));
Greg Kroah-Hartman
maintainerPATCH 645/737 f2fs: use f2fs_err_ratelimited() to avoid redundant logs
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chao Yu <[email protected]>
[ Upstream commit 0b8eb814e05885cde53c1d56ee012a029b8413e6 ]
Use f2fs_err_ratelimited() to instead f2fs_err() in f2fs_record_stop_reason() and f2fs_record_errors() to avoid redundant logs.
Stable-dep-of: ca8b201f2854 ("f2fs: fix to avoid potential deadlock")
--- fs/f2fs/super.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
fs/f2fs/super.c +6 -3
@@ -4054,7 +4054,9 @@ static void f2fs_record_stop_reason(struf2fs_up_write (&sbi->sb_lock);if (err) -f2fs_err (sbi,"f2fs_commit_super fails to record err:%d" , err); +f2fs_err_ratelimited (sbi, +"f2fs_commit_super fails to record stop_reason, err:%d" , + err); }void f2fs_save_errors (struct f2fs_sb_info *sbi,unsigned char flag)
@@ -4097,8 +4099,9 @@ static void f2fs_record_errors(struct f2 err =f2fs_commit_super (sbi, false);if (err) -f2fs_err (sbi,"f2fs_commit_super fails to record errors:%u, err:%d" , - error, err); +f2fs_err_ratelimited (sbi, +"f2fs_commit_super fails to record errors:%u, err:%d" , + error, err); out_unlock:f2fs_up_write (&sbi->sb_lock); }
Greg Kroah-Hartman
maintainerPATCH 646/737 f2fs: fix to avoid potential deadlock
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chao Yu <[email protected]>
[ Upstream commit ca8b201f28547e28343a6f00a6e91fa8c09572fe ]
As Jiaming Zhang and syzbot reported, there is potential deadlock in f2fs as below:
Chain exists of: &sbi->cp_rwsem --> fs_reclaim --> sb_internal#2 Possible unsafe locking scenario:
CPU0 CPU1
---- ----
rlock(sb_internal#2);
lock(fs_reclaim);
lock(sb_internal#2); rlock(&sbi->cp_rwsem);
*** DEADLOCK ***
3 locks held by kswapd0/73:
#0: ffffffff8e247a40 (fs_reclaim){+.+.}-{0:0}, at: balance_pgdat mm/vmscan.c:7015 [inline] #0: ffffffff8e247a40 (fs_reclaim){+.+.}-{0:0}, at: kswapd+0x951/0x2800 mm/vmscan.c:7389 #1: ffff8880118400e0 (&type->s_umount_key#50){.+.+}-{4:4}, at: super_trylock_shared fs/super.c:562 [inline] #1: ffff8880118400e0 (&type->s_umount_key#50){.+.+}-{4:4}, at: super_cache_scan+0x91/0x4b0 fs/super.c:197 #2: ffff888011840610 (sb_internal#2){.+.+}-{0:0}, at: f2fs_evict_inode+0x8d9/0x1b60 fs/f2fs/inode.c:890
stack backtrace: CPU: 0 UID: 0 PID: 73 Comm: kswapd0 Not tainted syzkaller #0 PREEMPT(full) Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 Call Trace: <TASK> dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120 print_circular_bug+0x2ee/0x310 kernel/locking/lockdep.c:2043 check_noncircular+0x134/0x160 kernel/locking/lockdep.c:2175 check_prev_add kernel/locking/lockdep.c:3165 [inline] check_prevs_add kernel/locking/lockdep.c:3284 [inline] validate_chain+0xb9b/0x2140 kernel/locking/lockdep.c:3908 __lock_acquire+0xab9/0xd20 kernel/locking/lockdep.c:5237 lock_acquire+0x120/0x360 kernel/locking/lockdep.c:5868 down_read+0x46/0x2e0 kernel/locking/rwsem.c:1537 f2fs_down_read fs/f2fs/f2fs.h:2278 [inline] f2fs_lock_op fs/f2fs/f2fs.h:2357 [inline] f2fs_do_truncate_blocks+0x21c/0x10c0 fs/f2fs/file.c:791 f2fs_truncate_blocks+0x10a/0x300 fs/f2fs/file.c:867 f2fs_truncate+0x489/0x7c0 fs/f2fs/file.c:925 f2fs_evict_inode+0x9f2/0x1b60 fs/f2fs/inode.c:897 evict+0x504/0x9c0 fs/inode.c:810 f2fs_evict_inode+0x1dc/0x1b60 fs/f2fs/inode.c:853 evict+0x504/0x9c0 fs/inode.c:810 dispose_list fs/inode.c:852 [inline] prune_icache_sb+0x21b/0x2c0 fs/inode.c:1000 super_cache_scan+0x39b/0x4b0 fs/super.c:224 do_shrink_slab+0x6ef/0x1110 mm/shrinker.c:437 shrink_slab_memcg mm/shrinker.c:550 [inline] shrink_slab+0x7ef/0x10d0 mm/shrinker.c:628 shrink_one+0x28a/0x7c0 mm/vmscan.c:4955 shrink_many mm/vmscan.c:5016 [inline] lru_gen_shrink_node mm/vmscan.c:5094 [inline] shrink_node+0x315d/0x3780 mm/vmscan.c:6081 kswapd_shrink_node mm/vmscan.c:6941 [inline] balance_pgdat mm/vmscan.c:7124 [inline] kswapd+0x147c/0x2800 mm/vmscan.c:7389 kthread+0x70e/0x8a0 kernel/kthread.c:463 ret_from_fork+0x4bc/0x870 arch/x86/kernel/process.c:158 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 </TASK>
The root cause is deadlock among four locks as below:
kswapd
- fs_reclaim --- Lock A
- shrink_one
- evict
- f2fs_evict_inode
- sb_start_intwrite --- Lock B
- iput
- evict
- f2fs_evict_inode
- sb_start_intwrite --- Lock B
- f2fs_truncate
- f2fs_truncate_blocks
- f2fs_do_truncate_blocks
- f2fs_lock_op --- Lock C
ioctl
- f2fs_ioc_commit_atomic_write
- f2fs_lock_op --- Lock C
- __f2fs_commit_atomic_write
- __replace_atomic_write_block
- f2fs_get_dnode_of_data
- __get_node_folio
- f2fs_check_nid_range
- f2fs_handle_error
- f2fs_record_errors
- f2fs_down_write --- Lock D
open
- do_open
- do_truncate
- security_inode_need_killpriv
- f2fs_getxattr
- lookup_all_xattrs
- f2fs_handle_error
- f2fs_record_errors
- f2fs_down_write --- Lock D
- f2fs_commit_super
- read_mapping_folio
- filemap_alloc_folio_noprof
- prepare_alloc_pages
- fs_reclaim_acquire --- Lock A
In order to avoid such deadlock, we need to avoid grabbing sb_lock in f2fs_handle_error(), so, let's use asynchronous method instead:
- remove f2fs_handle_error() implementation
- rename f2fs_handle_error_async() to f2fs_handle_error()
- spread f2fs_handle_error()
--- fs/f2fs/compress.c | 5 +---- fs/f2fs/f2fs.h | 1 - fs/f2fs/super.c | 41 ----------------------------------------- 3 files changed, 1 insertion(+), 46 deletions(-)
fs/f2fs/compress.c +1 -4
@@ -754,10 +754,7 @@ void f2fs_decompress_cluster(struct deco ret = -EFSCORRUPTED ;/* Avoid f2fs_commit_super in irq context */ -if (!in_task) -f2fs_handle_error_async (sbi,ERROR_FAIL_DECOMPRESSION ); -else -f2fs_handle_error (sbi,ERROR_FAIL_DECOMPRESSION ); +f2fs_handle_error (sbi,ERROR_FAIL_DECOMPRESSION ); goto out_release; }
fs/f2fs/f2fs.h +0 -1
@@ -3638,7 +3638,6 @@ void f2fs_quota_off_umount(struct super_void f2fs_save_errors (struct f2fs_sb_info *sbi,unsigned char flag);void f2fs_handle_critical_error (struct f2fs_sb_info *sbi,unsigned char reason);void f2fs_handle_error (struct f2fs_sb_info *sbi,unsigned char error); -void f2fs_handle_error_async (struct f2fs_sb_info *sbi,unsigned char error);int f2fs_commit_super (struct f2fs_sb_info *sbi,bool recover);int f2fs_sync_fs (struct super_block *sb,int sync);int f2fs_sanity_check_ckpt (struct f2fs_sb_info *sbi);
fs/f2fs/super.c +0 -41
50 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 647/737 NFSD: Clear SECLABEL in the suppattr_exclcreat bitmap
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 27d17641cacfedd816789b75d342430f6b912bd2 ]
Quoted 1 line
Quoted 1 line
From RFC 8881:
5.8.1.14. Attribute 75: suppattr_exclcreat
Quoted 4 lines
The bit vector that would set all REQUIRED and RECOMMENDED attributes that are supported by the
EXCLUSIVE4_1method of file creation via the OPEN operation. The scope of this attribute applies to all objects with a matching fsid.
There's nothing in RFC 8881 that states that suppattr_exclcreat is or is not allowed to contain bits for attributes that are clear in the reported supported_attrs bitmask. But it doesn't make sense for an NFS server to indicate that it /doesn't/ implement an attribute, but then also indicate that clients /are/ allowed to set that attribute using OPEN(create) with EXCLUSIVE4_1.
Ensure that the SECURITY_LABEL and ACL bits are not set in the suppattr_exclcreat bitmask when they are also not set in the supported_attrs bitmask.
--- fs/nfsd/nfs4xdr.c | 5 +++++ 1 file changed, 5 insertions(+)
fs/nfsd/nfs4xdr.c +5 -0
@@ -3419,6 +3419,11 @@ out_acl:u32 supp[3 ];memcpy (supp, nfsd_suppattrs[minorversion],sizeof (supp)); +if (!IS_POSIXACL (d_inode (dentry))) + supp[0 ] &= ~FATTR4_WORD0_ACL ; +if (!contextsupport) + supp[2 ] &= ~FATTR4_WORD2_SECURITY_LABEL ; + supp[0 ] &=NFSD_SUPPATTR_EXCLCREAT_WORD0 ; supp[1 ] &=NFSD_SUPPATTR_EXCLCREAT_WORD1 ; supp[2 ] &=NFSD_SUPPATTR_EXCLCREAT_WORD2 ;
Greg Kroah-Hartman
maintainerPATCH 648/737 gpiolib: acpi: Add quirk for Dell Precision 7780
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Askar Safin <[email protected]>
[ Upstream commit 2d967310c49ed93ac11cef408a55ddf15c3dd52e ]
Dell Precision 7780 often wakes up on its own from suspend. Sometimes wake up happens immediately (i. e. within 7 seconds), sometimes it happens after, say, 30 minutes.
--- drivers/gpio/gpiolib-acpi.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
drivers/gpio/gpiolib-acpi.c +22 -0
@@ -1720,6 +1720,28 @@ static const struct dmi_system_id gpioli .ignore_interrupt = "AMDI0030:00@11", }, }, + { + /* + * Spurious wakeups, likely from touchpad controller + * Dell Precision 7780 + * Found in BIOS 1.24.1 + * + * Found in touchpad firmware, installed by Dell Touchpad Firmware Update Utility version 1160.4196.9, A01 + * ( Dell-Touchpad-Firmware-Update-Utility_VYGNN_WIN64_1160.4196.9_A00.EXE ), + * released on 11 Jul 2024 + * + * https://lore.kernel.org/linux-i2c/[email protected]/ + */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_FAMILY, "Precision"), + DMI_MATCH(DMI_PRODUCT_NAME, "Precision 7780"), + DMI_MATCH(DMI_BOARD_NAME, "0C6JVW"), + }, + .driver_data = &(struct acpi_gpiolib_dmi_quirk) { + .ignore_wake = "VEN_0488:00@355", + }, + }, {} /* Terminating entry */ };
Greg Kroah-Hartman
maintainerPATCH 649/737 ARM: dts: microchip: sama7g5: fix uart fifo size to 32
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolas Ferre <[email protected]>
[ Upstream commit 5654889a94b0de5ad6ceae3793e7f5e0b61b50b6 ]
On some flexcom nodes related to uart, the fifo sizes were wrong: fix them to 32 data.
--- arch/arm/boot/dts/microchip/sama7g5.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm/boot/dts/microchip/sama7g5.dtsi +2 -2
@@ -811,7 +811,7 @@ dma-names = "tx", "rx"; atmel,use-dma-rx; atmel,use-dma-tx; - atmel,fifo-size = <16>; + atmel,fifo-size = <32>; status = "disabled"; }; };
@@ -837,7 +837,7 @@ dma-names = "tx", "rx"; atmel,use-dma-rx; atmel,use-dma-tx; - atmel,fifo-size = <16>; + atmel,fifo-size = <32>; status = "disabled"; }; };
Greg Kroah-Hartman
maintainerPATCH 650/737 svcrdma: bound check rq_pages index in inline path
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joshua Rogers <[email protected]>
[ Upstream commit d1bea0ce35b6095544ee82bb54156fc62c067e58 ]
svc_rdma_copy_inline_range indexed rqstp->rq_pages[rc_curpage] without verifying rc_curpage stays within the allocated page array. Add guards before the first use and after advancing to a new page.
--- net/sunrpc/xprtrdma/svc_rdma_rw.c | 3 +++ 1 file changed, 3 insertions(+)
net/sunrpc/xprtrdma/svc_rdma_rw.c +3 -0
@@ -815,6 +815,9 @@ static int svc_rdma_copy_inline_range(stfor (page_no =0 ; page_no < numpages; page_no++) {unsigned int page_len; +if (info->ri_pageno >=RPCSVC_MAXPAGES ) +return -EINVAL ; + page_len = min_t(unsigned int, remaining,PAGE_SIZE - info->ri_pageoff);
Greg Kroah-Hartman
maintainerPATCH 651/737 fuse: fix readahead reclaim deadlock
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joanne Koong <[email protected]>
[ Upstream commit bd5603eaae0aabf527bfb3ce1bb07e979ce5bd50 ]
Commit e26ee4efbc79 ("fuse: allocate ff->release_args only if release is needed") skips allocating ff->release_args if the server does not implement open. However in doing so, fuse_prepare_release() now skips grabbing the reference on the inode, which makes it possible for an inode to be evicted from the dcache while there are inflight readahead requests. This causes a deadlock if the server triggers reclaim while servicing the readahead request and reclaim attempts to evict the inode of the file being read ahead. Since the folio is locked during readahead, when reclaim evicts the fuse inode and fuse_evict_inode() attempts to remove all folios associated with the inode from the page cache (truncate_inode_pages_range()), reclaim will block forever waiting for the lock since readahead cannot relinquish the lock because it is itself blocked in reclaim:
Quoted 1 line
Quoted 1 line
Quoted 1 line
stack_trace(1504735)
folio_wait_bit_common (mm/filemap.c:1308:4) folio_lock (./include/linux/pagemap.h:1052:3) truncate_inode_pages_range (mm/truncate.c:336:10) fuse_evict_inode (fs/fuse/inode.c:161:2) evict (fs/inode.c:704:3) dentry_unlink_inode (fs/dcache.c:412:3) __dentry_kill (fs/dcache.c:615:3) shrink_kill (fs/dcache.c:1060:12) shrink_dentry_list (fs/dcache.c:1087:3) prune_dcache_sb (fs/dcache.c:1168:2) super_cache_scan (fs/super.c:221:10) do_shrink_slab (mm/shrinker.c:435:9) shrink_slab (mm/shrinker.c:626:10) shrink_node (mm/vmscan.c:5951:2) shrink_zones (mm/vmscan.c:6195:3) do_try_to_free_pages (mm/vmscan.c:6257:3) do_swap_page (mm/memory.c:4136:11) handle_pte_fault (mm/memory.c:5562:10) handle_mm_fault (mm/memory.c:5870:9) do_user_addr_fault (arch/x86/mm/fault.c:1338:10) handle_page_fault (arch/x86/mm/fault.c:1481:3) exc_page_fault (arch/x86/mm/fault.c:1539:2) asm_exc_page_fault+0x22/0x27
Fix this deadlock by allocating ff->release_args and grabbing the reference on the inode when preparing the file for release even if the server does not implement open. The inode reference will be dropped when the last reference on the fuse file is dropped (see fuse_file_put() -> fuse_release_end()).
--- fs/fuse/file.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-)
fs/fuse/file.c +19 -7
@@ -113,7 +113,9 @@ static void fuse_file_put(struct fuse_fistruct fuse_args *args = (ra ? &ra->args :NULL );if (!args) { -/* Do nothing when server does not implement 'open' */ +/* Do nothing when server does not implement 'opendir' */ + }else if (args->opcode ==FUSE_RELEASE && ff->fm->fc->no_open) { +fuse_release_end (ff->fm, args,0 ); }else if (sync) {fuse_simple_request (ff->fm, args);fuse_release_end (ff->fm, args,0 );
@@ -134,8 +136,17 @@ struct fuse_file *fuse_file_open(structstruct fuse_file *ff;int opcode = isdir ?FUSE_OPENDIR :FUSE_OPEN ;bool open = isdir ? !fc->no_opendir : !fc->no_open; +bool release = !isdir || open; - ff =fuse_file_alloc (fm, open); +/* +* ff->args->release_args still needs to be allocated (so we can hold an +* inode reference while there are pending inflight file operations when +* ->release() is called, see fuse_prepare_release()) even if +* fc->no_open is set else it becomes possible for reclaim to deadlock +* if while servicing the readahead request the server triggers reclaim +* and reclaim evicts the inode of the file being read ahead. +*/ + ff =fuse_file_alloc (fm, release);if (!ff)return ERR_PTR (-ENOMEM );
@@ -154,13 +165,14 @@ struct fuse_file *fuse_file_open(structfuse_file_free (ff);return ERR_PTR (err); }else { -/* No release needed */ -kfree (ff->release_args); - ff->release_args =NULL ; -if (isdir) +if (isdir) { +/* No release needed */ +kfree (ff->release_args); + ff->release_args =NULL ; fc->no_opendir =1 ; -else + }else { fc->no_open =1 ; + } } }
Greg Kroah-Hartman
maintainerPATCH 652/737 PCI: brcmstb: Fix disabling L0s capability
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jim Quinlan <[email protected]>
[ Upstream commit 9583f9d22991d2cfb5cc59a2552040c4ae98d998 ]
caab002d5069 ("PCI: brcmstb: Disable L0s component of ASPM if requested") set PCI_EXP_LNKCAP_ASPM_L1 and (optionally) PCI_EXP_LNKCAP_ASPM_L0S in PCI_EXP_LNKCAP (aka PCIE_RC_CFG_PRIV1_LINK_CAPABILITY in brcmstb).
But instead of using PCI_EXP_LNKCAP_ASPM_L1 and PCI_EXP_LNKCAP_ASPM_L0S directly, it used PCIE_LINK_STATE_L1 and PCIE_LINK_STATE_L0S, which are Linux-created values that only coincidentally matched the PCIe spec. b478e162f227 ("PCI/ASPM: Consolidate link state defines") later changed them so they no longer matched the PCIe spec, so the bits ended up in the wrong place in PCI_EXP_LNKCAP.
Use PCI_EXP_LNKCAP_ASPM_L0S to clear L0s support when there's an 'aspm-no-l0s' property. Rely on brcmstb hardware to advertise L0s and/or L1 support otherwise.
--- drivers/pci/controller/pcie-brcmstb.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-)
drivers/pci/controller/pcie-brcmstb.c +3 -7
@@ -46,7 +46,6 @@#define PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK 0xffffff#define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY 0x04dc -#define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK 0xc00#define PCIE_RC_DL_MDIO_ADDR 0x1100#define PCIE_RC_DL_MDIO_WR_DATA 0x1104
@@ -867,7 +866,7 @@ static int brcm_pcie_setup(struct brcm_pvoid __iomem *base = pcie->base;struct pci_host_bridge *bridge;struct resource_entry *entry; -u32 tmp, burst, aspm_support; +u32 tmp, burst;int num_out_wins =0 ;int ret, memc;
@@ -971,12 +970,9 @@ static int brcm_pcie_setup(struct brcm_pwritel (tmp, base +PCIE_MISC_RC_BAR3_CONFIG_LO );/* Don't advertise L0s capability if 'aspm-no-l0s' */ - aspm_support =PCIE_LINK_STATE_L1 ; -if (!of_property_read_bool (pcie->np,"aspm-no-l0s" )) - aspm_support |=PCIE_LINK_STATE_L0S ; tmp =readl (base +PCIE_RC_CFG_PRIV1_LINK_CAPABILITY ); -u32p_replace_bits (&tmp, aspm_support, -PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK ); +if (of_property_read_bool (pcie->np,"aspm-no-l0s" )) + tmp &= ~PCI_EXP_LNKCAP_ASPM_L0S ;writel (tmp, base +PCIE_RC_CFG_PRIV1_LINK_CAPABILITY );/*
Greg Kroah-Hartman
maintainerPATCH 653/737 mptcp: fallback earlier on simult connection
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paolo Abeni <[email protected]>
[ Upstream commit 71154bbe49423128c1c8577b6576de1ed6836830 ]
Syzkaller reports a simult-connect race leading to inconsistent fallback status:
WARNING: CPU: 3 PID: 33 at net/mptcp/subflow.c:1515 subflow_data_ready+0x40b/0x7c0 net/mptcp/subflow.c:1515 Modules linked in: CPU: 3 UID: 0 PID: 33 Comm: ksoftirqd/3 Not tainted syzkaller #0 PREEMPT(full) Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 RIP: 0010:subflow_data_ready+0x40b/0x7c0 net/mptcp/subflow.c:1515 Code: 89 ee e8 78 61 3c f6 40 84 ed 75 21 e8 8e 66 3c f6 44 89 fe bf 07 00 00 00 e8 c1 61 3c f6 41 83 ff 07 74 09 e8 76 66 3c f6 90 <0f> 0b 90 e8 6d 66 3c f6 48 89 df e8 e5 ad ff ff 31 ff 89 c5 89 c6 RSP: 0018:ffffc900006cf338 EFLAGS: 00010246 RAX: 0000000000000000 RBX: ffff888031acd100 RCX: ffffffff8b7f2abf RDX: ffff88801e6ea440 RSI: ffffffff8b7f2aca RDI: 0000000000000005 RBP: 0000000000000000 R08: 0000000000000005 R09: 0000000000000007 R10: 0000000000000004 R11: 0000000000002c10 R12: ffff88802ba69900 R13: 1ffff920000d9e67 R14: ffff888046f81800 R15: 0000000000000004 FS: 0000000000000000(0000) GS:ffff8880d69bc000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000560fc0ca1670 CR3: 0000000032c3a000 CR4: 0000000000352ef0 Call Trace: <TASK> tcp_data_queue+0x13b0/0x4f90 net/ipv4/tcp_input.c:5197 tcp_rcv_state_process+0xfdf/0x4ec0 net/ipv4/tcp_input.c:6922 tcp_v6_do_rcv+0x492/0x1740 net/ipv6/tcp_ipv6.c:1672 tcp_v6_rcv+0x2976/0x41e0 net/ipv6/tcp_ipv6.c:1918 ip6_protocol_deliver_rcu+0x188/0x1520 net/ipv6/ip6_input.c:438 ip6_input_finish+0x1e4/0x4b0 net/ipv6/ip6_input.c:489 NF_HOOK include/linux/netfilter.h:318 [inline] NF_HOOK include/linux/netfilter.h:312 [inline] ip6_input+0x105/0x2f0 net/ipv6/ip6_input.c:500 dst_input include/net/dst.h:471 [inline] ip6_rcv_finish net/ipv6/ip6_input.c:79 [inline] NF_HOOK include/linux/netfilter.h:318 [inline] NF_HOOK include/linux/netfilter.h:312 [inline] ipv6_rcv+0x264/0x650 net/ipv6/ip6_input.c:311 __netif_receive_skb_one_core+0x12d/0x1e0 net/core/dev.c:5979 __netif_receive_skb+0x1d/0x160 net/core/dev.c:6092 process_backlog+0x442/0x15e0 net/core/dev.c:6444 __napi_poll.constprop.0+0xba/0x550 net/core/dev.c:7494 napi_poll net/core/dev.c:7557 [inline] net_rx_action+0xa9f/0xfe0 net/core/dev.c:7684 handle_softirqs+0x216/0x8e0 kernel/softirq.c:579 run_ksoftirqd kernel/softirq.c:968 [inline] run_ksoftirqd+0x3a/0x60 kernel/softirq.c:960 smpboot_thread_fn+0x3f7/0xae0 kernel/smpboot.c:160 kthread+0x3c2/0x780 kernel/kthread.c:463 ret_from_fork+0x5d7/0x6f0 arch/x86/kernel/process.c:148 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 </TASK>
The TCP subflow can process the simult-connect syn-ack packet after transitioning to TCP_FIN1 state, bypassing the MPTCP fallback check, as the sk_state_change() callback is not invoked for * -> FIN_WAIT1 transitions.
That will move the msk socket to an inconsistent status and the next incoming data will hit the reported splat.
Close the race moving the simult-fallback check at the earliest possible stage - that is at syn-ack generation time.
About the fixes tags: [2] was supposed to also fix this issue introduced by [3]. [1] is required as a dependence: it was not explicitly marked as a fix, but it is one and it has already been backported before [3]. In other words, this commit should be backported up to [3], including [2] and [1] if that's not already there.
--- net/mptcp/options.c | 10 ++++++++++ net/mptcp/protocol.h | 6 ++---- net/mptcp/subflow.c | 10 +--------- 3 files changed, 13 insertions(+), 13 deletions(-)
net/mptcp/options.c +10 -0
@@ -408,6 +408,16 @@ bool mptcp_syn_options(struct sock *sk,*/ subflow->snd_isn =TCP_SKB_CB (skb)->end_seq;if (subflow->request_mptcp) { +if (unlikely (subflow_simultaneous_connect (sk))) { +WARN_ON_ONCE (!mptcp_try_fallback (sk)); + +/* Ensure mptcp_finish_connect() will not process the +* MPC handshake. +*/ + subflow->request_mptcp =0 ; +return false; + } + opts->suboptions =OPTION_MPTCP_MPC_SYN ; opts->csum_reqd =mptcp_is_checksum_enabled (sock_net (sk)); opts->allow_join_id0 =mptcp_allow_join_id0 (sock_net (sk));
net/mptcp/protocol.h +2 -4
@@ -1175,10 +1175,8 @@ static inline bool subflow_simultaneous_ {struct mptcp_subflow_context *subflow =mptcp_subflow_ctx (sk); -return (1 << sk->sk_state) & - (TCPF_ESTABLISHED |TCPF_FIN_WAIT1 |TCPF_FIN_WAIT2 |TCPF_CLOSING ) && -is_active_ssk (subflow) && - !subflow->conn_finished; +/* Note that the sk state implies !subflow->conn_finished. */ +return sk->sk_state ==TCP_SYN_RECV &&is_active_ssk (subflow); }#ifdef CONFIG_SYN_COOKIES
net/mptcp/subflow.c +1 -9
@@ -1793,18 +1793,10 @@ static void subflow_state_change(struct {struct mptcp_subflow_context *subflow =mptcp_subflow_ctx (sk);struct sock *parent = subflow->conn; -struct mptcp_sock *msk; +struct mptcp_sock *msk =mptcp_sk (parent);__subflow_state_change (sk); - msk =mptcp_sk (parent); -if (subflow_simultaneous_connect (sk)) { -WARN_ON_ONCE (!mptcp_try_fallback (sk)); -pr_fallback (msk); - subflow->conn_finished =1 ; -mptcp_propagate_state (parent, sk, subflow,NULL ); - } -/* as recvmsg() does not acquire the subflow socket for ssk selection * a fin packet carrying a DSS can be unnoticed if we don't trigger * the data available machinery here.
Greg Kroah-Hartman
maintainerPATCH 654/737 lockd: fix vfs_test_lock() calls
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: NeilBrown <[email protected]>
[ Upstream commit a49a2a1baa0c553c3548a1c414b6a3c005a8deba ]
Usage of vfs_test_lock() is somewhat confused. Documentation suggests it is given a "lock" but this is not the case. It is given a struct file_lock which contains some details of the sort of lock it should be looking for.
In particular passing a "file_lock" containing fl_lmops or fl_ops is meaningless and possibly confusing.
This is particularly problematic in lockd. nlmsvc_testlock() receives an initialised "file_lock" from xdr-decode, including manager ops and an owner. It then mistakenly passes this to vfs_test_lock() which might replace the owner and the ops. This can lead to confusion when freeing the lock.
The primary role of the 'struct file_lock' passed to vfs_test_lock() is to report a conflicting lock that was found, so it makes more sense for nlmsvc_testlock() to pass "conflock", which it uses for returning the conflicting lock.
With this change, freeing of the lock is not confused and code in __nlm4svc_proc_test() and __nlmsvc_proc_test() can be simplified.
Documentation for vfs_test_lock() is improved to reflect its real purpose, and a WARN_ON_ONCE() is added to avoid a similar problem in the future.
--- fs/lockd/svc4proc.c | 4 +--- fs/lockd/svclock.c | 21 ++++++++++++--------- fs/lockd/svcproc.c | 5 +---- fs/locks.c | 12 ++++++++++-- 4 files changed, 24 insertions(+), 18 deletions(-)
fs/lockd/svc4proc.c +1 -3
@@ -96,7 +96,6 @@ __nlm4svc_proc_test(struct svc_rqst *rqsstruct nlm_args *argp = rqstp->rq_argp;struct nlm_host *host;struct nlm_file *file; -struct nlm_lockowner *test_owner;__be32 rc = rpc_success;dprintk ("lockd: TEST4 called\n" );
@@ -106,7 +105,6 @@ __nlm4svc_proc_test(struct svc_rqst *rqsif ((resp->status =nlm4svc_retrieve_args (rqstp, argp, &host, &file)))return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; - test_owner = argp->lock.fl.fl_owner;/* Now check for conflicting locks */ resp->status =nlmsvc_testlock (rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie);if (resp->status == nlm_drop_reply)
@@ -114,7 +112,7 @@ __nlm4svc_proc_test(struct svc_rqst *rqselse dprintk ("lockd: TEST4 status %d\n" ,ntohl (resp->status)); -nlmsvc_put_lockowner (test_owner); +nlmsvc_release_lockowner (&argp->lock);nlmsvc_release_host (host);nlm_release_file (file);return rc;
fs/lockd/svclock.c +12 -9
@@ -615,7 +615,13 @@ nlmsvc_testlock(struct svc_rqst *rqstp, } mode =lock_to_openmode (&lock->fl); - error =vfs_test_lock (file->f_file[mode], &lock->fl); +locks_init_lock (&conflock->fl); +/* vfs_test_lock only uses start, end, and owner, but tests fl_file */ + conflock->fl.fl_file = lock->fl.fl_file; + conflock->fl.fl_start = lock->fl.fl_start; + conflock->fl.fl_end = lock->fl.fl_end; + conflock->fl.fl_owner = lock->fl.fl_owner; + error =vfs_test_lock (file->f_file[mode], &conflock->fl);if (error) {/* We can't currently deal with deferred test requests */ if (error ==FILE_LOCK_DEFERRED )
@@ -625,22 +631,19 @@ nlmsvc_testlock(struct svc_rqst *rqstp, goto out; } -if (lock->fl.fl_type ==F_UNLCK ) { +if (conflock->fl.fl_type ==F_UNLCK ) { ret = nlm_granted; goto out; }dprintk ("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n" , - lock->fl.fl_type, (long long )lock->fl.fl_start, - (long long )lock->fl.fl_end); + conflock->fl.fl_type, (long long )conflock->fl.fl_start, + (long long )conflock->fl.fl_end); conflock->caller ="somehost" ;/* FIXME */ conflock->len =strlen (conflock->caller); conflock->oh.len =0 ;/* don't return OH info */ - conflock->svid = lock->fl.fl_pid; - conflock->fl.fl_type = lock->fl.fl_type; - conflock->fl.fl_start = lock->fl.fl_start; - conflock->fl.fl_end = lock->fl.fl_end; -locks_release_private (&lock->fl); + conflock->svid = conflock->fl.fl_pid; +locks_release_private (&conflock->fl); ret = nlm_lck_denied; out:
fs/lockd/svcproc.c +1 -4
@@ -117,7 +117,6 @@ __nlmsvc_proc_test(struct svc_rqst *rqststruct nlm_args *argp = rqstp->rq_argp;struct nlm_host *host;struct nlm_file *file; -struct nlm_lockowner *test_owner;__be32 rc = rpc_success;dprintk ("lockd: TEST called\n" );
@@ -127,8 +126,6 @@ __nlmsvc_proc_test(struct svc_rqst *rqstif ((resp->status =nlmsvc_retrieve_args (rqstp, argp, &host, &file)))return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; - test_owner = argp->lock.fl.fl_owner; -/* Now check for conflicting locks */ resp->status =cast_status (nlmsvc_testlock (rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie));if (resp->status == nlm_drop_reply)
@@ -137,7 +134,7 @@ __nlmsvc_proc_test(struct svc_rqst *rqstdprintk ("lockd: TEST status %d vers %d\n" ,ntohl (resp->status), rqstp->rq_vers); -nlmsvc_put_lockowner (test_owner); +nlmsvc_release_lockowner (&argp->lock);nlmsvc_release_host (host);nlm_release_file (file);return rc;
fs/locks.c +10 -2
@@ -2124,13 +2124,21 @@ SYSCALL_DEFINE2(flock, unsigned int, fd,/** * vfs_test_lock - test file byte range lock * @filp: The file to test lock for -* @fl: The lock to test; also used to hold result +* @fl: The byte-range in the file to test; also used to hold result * +* On entry, @fl does not contain a lock, but identifies a range (fl_start, fl_end) +* in the file (c.flc_file), and an owner (c.flc_owner) for whom existing locks +* should be ignored. c.flc_type and c.flc_flags are ignored. +* Both fl_lmops and fl_ops in @fl must be NULL. * Returns -ERRNO on failure. Indicates presence of conflicting lock by -* setting conf->fl_type to something other than F_UNLCK. +* setting fl->fl_type to something other than F_UNLCK. +* +* If vfs_test_lock() does find a lock and return it, the caller must +* use locks_free_lock() or locks_release_private() on the returned lock. */ int vfs_test_lock (struct file *filp,struct file_lock *fl) { +WARN_ON_ONCE (fl->fl_ops || fl->fl_lmops);WARN_ON_ONCE (filp != fl->fl_file);if (filp->f_op->lock)return filp->f_op->lock (filp,F_GETLK , fl);
Greg Kroah-Hartman
maintainerPATCH 655/737 wifi: mac80211: Discard Beacon frames to non-broadcast address
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jouni Malinen <[email protected]>
[ Upstream commit 193d18f60588e95d62e0f82b6a53893e5f2f19f8 ]
Beacon frames are required to be sent to the broadcast address, see IEEE Std 802.11-2020, 11.1.3.1 ("The Address 1 field of the Beacon .. frame shall be set to the broadcast address"). A unicast Beacon frame might be used as a targeted attack to get one of the associated STAs to do something (e.g., using CSA to move it to another channel). As such, it is better have strict filtering for this on the received side and discard all Beacon frames that are sent to an unexpected address.
This is even more important for cases where beacon protection is used. The current implementation in mac80211 is correctly discarding unicast Beacon frames if the Protected Frame bit in the Frame Control field is set to 0. However, if that bit is set to 1, the logic used for checking for configured BIGTK(s) does not actually work. If the driver does not have logic for dropping unicast Beacon frames with Protected Frame bit 1, these frames would be accepted in mac80211 processing as valid Beacon frames even though they are not protected. This would allow beacon protection to be bypassed. While the logic for checking beacon protection could be extended to cover this corner case, a more generic check for discard all Beacon frames based on A1=unicast address covers this without needing additional changes.
Address all these issues by dropping received Beacon frames if they are sent to a non-broadcast address.
--- net/mac80211/rx.c | 5 +++++ 1 file changed, 5 insertions(+)
net/mac80211/rx.c +5 -0
@@ -3388,6 +3388,11 @@ ieee80211_rx_h_mgmt_check(struct ieee802 rx->skb->len < IEEE80211_MIN_ACTION_SIZE)return RX_DROP_U_RUNT_ACTION ; +/* Drop non-broadcast Beacon frames */ +if (ieee80211_is_beacon (mgmt->frame_control) && + !is_broadcast_ether_addr (mgmt->da)) +return RX_DROP_MONITOR ; +if (rx->sdata->vif.type ==NL80211_IFTYPE_AP &&ieee80211_is_beacon (mgmt->frame_control) && !(rx->flags &IEEE80211_RX_BEACON_REPORTED )) {
Greg Kroah-Hartman
maintainerPATCH 656/737 mm: simplify folio_expected_ref_count()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Hildenbrand <[email protected]>
[ Upstream commit 78cb1a13c42a6d843e21389f74d1edb90ed07288 ]
Now that PAGE_MAPPING_MOVABLE is gone, we can simplify and rely on the folio_test_anon() test only.
... but staring at the users, this function should never even have been called on movable_ops pages. E.g.,
* __buffer_migrate_folio() does not make sense for them
* folio_migrate_mapping() does not make sense for them
* migrate_huge_page_move_mapping() does not make sense for them
* __migrate_folio() does not make sense for them
* ... and khugepaged should never stumble over them
Let's simply refuse typed pages (which includes slab) except hugetlb, and WARN.
Stable-dep-of: f183663901f2 ("mm: consider non-anon swap cache folios in folio_expected_ref_count()")
--- include/linux/mm.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
include/linux/mm.h +2 -2
@@ -2194,13 +2194,13 @@ static inline int folio_expected_ref_couconst int order =folio_order (folio);int ref_count =0 ; -if (WARN_ON_ONCE (folio_test_slab (folio))) +if (WARN_ON_ONCE (page_has_type (&folio->page) && !folio_test_hugetlb (folio)))return 0 ;if (folio_test_anon (folio)) {/* One reference per page from the swapcache. */ ref_count +=folio_test_swapcache (folio) << order; - }else if (!((unsigned long )folio->mapping &PAGE_MAPPING_FLAGS )) { + }else {/* One reference per page from the pagecache. */ ref_count += !!folio->mapping << order;/* One reference from PG_private. */
Greg Kroah-Hartman
maintainerPATCH 657/737 mm: consider non-anon swap cache folios in folio_expected_ref_count()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bijan Tabatabai <[email protected]>
[ Upstream commit f183663901f21fe0fba8bd31ae894bc529709ee0 ]
Currently, folio_expected_ref_count() only adds references for the swap cache if the folio is anonymous. However, according to the comment above the definition of PG_swapcache in enum pageflags, shmem folios can also have PG_swapcache set. This patch makes sure references for the swap cache are added if folio_test_swapcache(folio) is true.
This issue was found when trying to hot-unplug memory in a QEMU/KVM virtual machine. When initiating hot-unplug when most of the guest memory is allocated, hot-unplug hangs partway through removal due to migration failures. The following message would be printed several times, and would be printed again about every five seconds:
[ 49.641309] migrating pfn b12f25 failed ret:7 [ 49.641310] page: refcount:2 mapcount:0 mapping:0000000033bd8fe2 index:0x7f404d925 pfn:0xb12f25 [ 49.641311] aops:swap_aops [ 49.641313] flags: 0x300000000030508(uptodate|active|owner_priv_1|reclaim|swapbacked|node=0|zone=3) [ 49.641314] raw: 0300000000030508 ffffed312c4bc908 ffffed312c4bc9c8 0000000000000000 [ 49.641315] raw: 00000007f404d925 00000000000c823b 00000002ffffffff 0000000000000000 [ 49.641315] page dumped because: migration failure
When debugging this, I found that these migration failures were due to __migrate_folio() returning -EAGAIN for a small set of folios because the expected reference count it calculates via folio_expected_ref_count() is one less than the actual reference count of the folios. Furthermore, all of the affected folios were not anonymous, but had the PG_swapcache flag set, inspiring this patch. After applying this patch, the memory hot-unplug behaves as expected.
I tested this on a machine running Ubuntu 24.04 with kernel version 6.8.0-90-generic and 64GB of memory. The guest VM is managed by libvirt and runs Ubuntu 24.04 with kernel version 6.18 (though the head of the mm-unstable branch as a Dec 16, 2025 was also tested and behaves the same) and 48GB of memory. The libvirt XML definition for the VM can be found at [1]. CONFIG_MHP_DEFAULT_ONLINE_TYPE_ONLINE_MOVABLE is set in the guest kernel so the hot-pluggable memory is automatically onlined.
Below are the steps to reproduce this behavior:
1) Define and start and virtual machine
host$ virsh -c qemu:///system define ./test_vm.xml # test_vm.xml from [1] host$ virsh -c qemu:///system start test_vm
2) Setup swap in the guest
guest$ sudo fallocate -l 32G /swapfile
guest$ sudo chmod 0600 /swapfile
guest$ sudo mkswap /swapfile
guest$ sudo swapon /swapfile
3) Use alloc_data [2] to allocate most of the remaining guest memory guest$ ./alloc_data 45
4) In a separate guest terminal, monitor the amount of used memory guest$ watch -n1 free -h
5) When alloc_data has finished allocating, initiate the memory hot-unplug using the provided xml file [3]
host$ virsh -c qemu:///system detach-device test_vm ./remove.xml --live
After initiating the memory hot-unplug, you should see the amount of available memory in the guest decrease, and the amount of used swap data increase. If everything works as expected, when all of the memory is unplugged, there should be around 8.5-9GB of data in swap. If the unplugging is unsuccessful, the amount of used swap data will settle below that. If that happens, you should be able to see log messages in dmesg similar to the one posted above.
--- include/linux/mm.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
include/linux/mm.h +4 -4
@@ -2197,10 +2197,10 @@ static inline int folio_expected_ref_couif (WARN_ON_ONCE (page_has_type (&folio->page) && !folio_test_hugetlb (folio)))return 0 ; -if (folio_test_anon (folio)) { -/* One reference per page from the swapcache. */ - ref_count +=folio_test_swapcache (folio) << order; - }else { +/* One reference per page from the swapcache. */ + ref_count +=folio_test_swapcache (folio) << order; + +if (!folio_test_anon (folio)) {/* One reference per page from the pagecache. */ ref_count += !!folio->mapping << order;/* One reference from PG_private. */
Greg Kroah-Hartman
maintainerPATCH 658/737 pmdomain: Use device_get_match_data()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rob Herring <[email protected]>
[ Upstream commit 3ba9fdfaa550936837b50b73d6c27ac401fde875 ]
Use preferred device_get_match_data() instead of of_match_device() to get the driver match data. With this, adjust the includes to explicitly include the correct headers.
Stable-dep-of: 73cb5f6eafb0 ("pmdomain: imx: Fix reference count leak in imx_gpc_probe()")
--- drivers/pmdomain/actions/owl-sps.c | 16 +++++----------- drivers/pmdomain/imx/gpc.c | 7 +++---- drivers/pmdomain/rockchip/pm-domains.c | 13 ++++--------- 3 files changed, 12 insertions(+), 24 deletions(-)
drivers/pmdomain/actions/owl-sps.c +5 -11
@@ -8,8 +8,10 @@* Copyright (c) 2017 Andreas Färber */ +#include <linux/mod_devicetable.h> #include <linux/of_address.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> +#include <linux/property.h> #include <linux/pm_domain.h> #include <linux/soc/actions/owl-sps.h> #include <dt-bindings/power/owl-s500-powergate.h>
@@ -96,24 +98,16 @@ static int owl_sps_init_domain(struct owstatic int owl_sps_probe (struct platform_device *pdev) { -const struct of_device_id *match;const struct owl_sps_info *sps_info;struct owl_sps *sps;int i, ret; -if (!pdev->dev.of_node) { -dev_err (&pdev->dev,"no device node\n" ); -return -ENODEV ; - } - - match =of_match_device (pdev->dev.driver->of_match_table, &pdev->dev); -if (!match || !match->data) { + sps_info =device_get_match_data (&pdev->dev); +if (!sps_info) {dev_err (&pdev->dev,"unknown compatible or missing data\n" );return -EINVAL ; } - sps_info = match->data; - sps =devm_kzalloc (&pdev->dev,struct_size (sps, domains, sps_info->num_domains),GFP_KERNEL );
drivers/pmdomain/imx/gpc.c +3 -4
@@ -7,9 +7,10 @@#include <linux/clk.h> #include <linux/delay.h> #include <linux/io.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_domain.h> +#include <linux/property.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h>
@@ -403,9 +404,7 @@ clk_err:static int imx_gpc_probe (struct platform_device *pdev) { -const struct of_device_id *of_id = -of_match_device (imx_gpc_dt_ids, &pdev->dev); -const struct imx_gpc_dt_data *of_id_data = of_id->data; +const struct imx_gpc_dt_data *of_id_data =device_get_match_data (&pdev->dev);struct device_node *pgc_node;struct regmap *regmap;void __iomem *base;
drivers/pmdomain/rockchip/pm-domains.c +4 -9
@@ -9,11 +9,13 @@#include <linux/iopoll.h> #include <linux/err.h> #include <linux/mutex.h> +#include <linux/platform_device.h> #include <linux/pm_clock.h> #include <linux/pm_domain.h> +#include <linux/property.h> +#include <linux/of.h> #include <linux/of_address.h> #include <linux/of_clk.h> -#include <linux/of_platform.h> #include <linux/clk.h> #include <linux/regmap.h> #include <linux/mfd/syscon.h>
@@ -857,7 +859,6 @@ static int rockchip_pm_domain_probe(strustruct device_node *node;struct device *parent;struct rockchip_pmu *pmu; -const struct of_device_id *match;const struct rockchip_pmu_info *pmu_info;int error;
@@ -866,13 +867,7 @@ static int rockchip_pm_domain_probe(strureturn -ENODEV ; } - match =of_match_device (dev->driver->of_match_table, dev); -if (!match || !match->data) { -dev_err (dev,"missing pmu data\n" ); -return -EINVAL ; - } - - pmu_info = match->data; + pmu_info =device_get_match_data (dev); pmu = devm_kzalloc(dev, struct_size(pmu, domains, pmu_info->num_domains),
Greg Kroah-Hartman
maintainerPATCH 659/737 pmdomain: imx: Fix reference count leak in imx_gpc_probe()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wentao Liang <[email protected]>
[ Upstream commit 73cb5f6eafb0ac7aea8cdeb8ff12981aa741d8fb ]
of_get_child_by_name() returns a node pointer with refcount incremented. Use the __free() attribute to manage the pgc_node reference, ensuring automatic of_node_put() cleanup when pgc_node goes out of scope.
This eliminates the need for explicit error handling paths and avoids reference count leaks.
--- drivers/pmdomain/imx/gpc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/pmdomain/imx/gpc.c +2 -3
@@ -405,13 +405,12 @@ clk_err:static int imx_gpc_probe (struct platform_device *pdev) {const struct imx_gpc_dt_data *of_id_data =device_get_match_data (&pdev->dev); -struct device_node *pgc_node; + struct device_node *pgc_node __free(device_node) + =of_get_child_by_name (pdev->dev.of_node,"pgc" );struct regmap *regmap;void __iomem *base;int ret; - pgc_node =of_get_child_by_name (pdev->dev.of_node,"pgc" ); -/* bail out if DT too old and doesn't provide the necessary info */ if (!of_property_read_bool (pdev->dev.of_node,"#power-domain-cells" ) && !pgc_node)
Greg Kroah-Hartman
maintainerPATCH 660/737 net: phy: mediatek: fix nvmem cell reference leak in mt798x_phy_calibration
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miaoqian Lin <[email protected]>
[ Upstream commit 1e5a541420b8c6d87d88eb50b6b978cdeafee1c9 ]
When nvmem_cell_read() fails in mt798x_phy_calibration(), the function returns without calling nvmem_cell_put(), leaking the cell reference.
Move nvmem_cell_put() right after nvmem_cell_read() to ensure the cell reference is always released regardless of the read result.
Found via static analysis and code review.
--- drivers/net/phy/mediatek-ge-soc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/phy/mediatek-ge-soc.c +1 -1
@@ -1082,9 +1082,9 @@ static int mt798x_phy_calibration(struct } buf = (u32 *)nvmem_cell_read (cell, &len); +nvmem_cell_put (cell);if (IS_ERR (buf))return PTR_ERR (buf); -nvmem_cell_put (cell);if (!buf[0 ] || !buf[1 ] || !buf[2 ] || !buf[3 ] || len <4 *sizeof (u32)) {phydev_err (phydev,"invalid efuse data\n" );
Greg Kroah-Hartman
maintainerPATCH 661/737 mptcp: ensure context reset on disconnect()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paolo Abeni <[email protected]>
[ Upstream commit 86730ac255b0497a272704de9a1df559f5d6602e ]
After the blamed commit below, if the MPC subflow is already in TCP_CLOSE status or has fallback to TCP at mptcp_disconnect() time, mptcp_do_fastclose() skips setting the send_fastclose flag and the later __mptcp_close_ssk() does not reset anymore the related subflow context.
Any later connection will be created with both the request_mptcp flag and the msk-level fallback status off (it is unconditionally cleared at MPTCP disconnect time), leading to a warning in subflow_data_ready():
WARNING: CPU: 26 PID: 8996 at net/mptcp/subflow.c:1519 subflow_data_ready (net/mptcp/subflow.c:1519 (discriminator 13)) Modules linked in: CPU: 26 UID: 0 PID: 8996 Comm: syz.22.39 Not tainted 6.18.0-rc7-05427-g11fc074f6c36 #1 PREEMPT(voluntary) Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 RIP: 0010:subflow_data_ready (net/mptcp/subflow.c:1519 (discriminator 13)) Code: 90 0f 0b 90 90 e9 04 fe ff ff e8 b7 1e f5 fe 89 ee bf 07 00 00 00 e8 db 19 f5 fe 83 fd 07 0f 84 35 ff ff ff e8 9d 1e f5 fe 90 <0f> 0b 90 e9 27 ff ff ff e8 8f 1e f5 fe 4c 89 e7 48 89 de e8 14 09 RSP: 0018:ffffc9002646fb30 EFLAGS: 00010293 RAX: 0000000000000000 RBX: ffff88813b218000 RCX: ffffffff825c8435 RDX: ffff8881300b3580 RSI: ffffffff825c8443 RDI: 0000000000000005 RBP: 000000000000000b R08: ffffffff825c8435 R09: 000000000000000b R10: 0000000000000005 R11: 0000000000000007 R12: ffff888131ac0000 R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000 FS: 00007f88330af6c0(0000) GS:ffff888a93dd2000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f88330aefe8 CR3: 000000010ff59000 CR4: 0000000000350ef0 Call Trace: <TASK> tcp_data_ready (net/ipv4/tcp_input.c:5356) tcp_data_queue (net/ipv4/tcp_input.c:5445) tcp_rcv_state_process (net/ipv4/tcp_input.c:7165) tcp_v4_do_rcv (net/ipv4/tcp_ipv4.c:1955) __release_sock (include/net/sock.h:1158 (discriminator 6) net/core/sock.c:3180 (discriminator 6)) release_sock (net/core/sock.c:3737) mptcp_sendmsg (net/mptcp/protocol.c:1763 net/mptcp/protocol.c:1857) inet_sendmsg (net/ipv4/af_inet.c:853 (discriminator 7)) __sys_sendto (net/socket.c:727 (discriminator 15) net/socket.c:742 (discriminator 15) net/socket.c:2244 (discriminator 15)) __x64_sys_sendto (net/socket.c:2247) do_syscall_64 (arch/x86/entry/syscall_64.c:63 (discriminator 1) arch/x86/entry/syscall_64.c:94 (discriminator 1)) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130) RIP: 0033:0x7f883326702d
Address the issue setting an explicit fastclosing flag at fastclose time, and checking such flag after mptcp_do_fastclose().
--- net/mptcp/protocol.c | 8 +++++--- net/mptcp/protocol.h | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-)
net/mptcp/protocol.c +5 -3
@@ -2441,10 +2441,10 @@ bool __mptcp_retransmit_pending_data(str*/ static void __mptcp_subflow_disconnect (struct sock *ssk,struct mptcp_subflow_context *subflow, -unsigned int flags) +bool fastclosing) {if (((1 << ssk->sk_state) & (TCPF_CLOSE |TCPF_LISTEN )) || - subflow->send_fastclose) { + fastclosing) {/* The MPTCP code never wait on the subflow sockets, TCP-level * disconnect should never fail */
@@ -2496,7 +2496,7 @@ static void __mptcp_close_ssk(struct soc need_push = (flags &MPTCP_CF_PUSH ) &&__mptcp_retransmit_pending_data (sk);if (!dispose_it) { -__mptcp_subflow_disconnect (ssk, subflow, flags); +__mptcp_subflow_disconnect (ssk, subflow, msk->fastclosing);release_sock (ssk); goto out;
@@ -2808,6 +2808,7 @@ static void mptcp_do_fastclose(struct sostruct mptcp_sock *msk =mptcp_sk (sk);mptcp_set_state (sk,TCP_CLOSE ); + msk->fastclosing =1 ;/* Explicitly send the fastclose reset as need */ if (__mptcp_check_fallback (msk))
@@ -3320,6 +3321,7 @@ static int mptcp_disconnect(struct sock msk->bytes_sent =0 ; msk->bytes_retrans =0 ; msk->rcvspace_init =0 ; + msk->fastclosing =0 ;WRITE_ONCE (sk->sk_shutdown,0 );sk_error_report (sk);
net/mptcp/protocol.h +2 -1
@@ -305,7 +305,8 @@ struct mptcp_sock { fastopening:1, in_accept_queue:1, free_first:1, - rcvspace_init:1; + rcvspace_init:1, + fastclosing:1;int keepalive_cnt;int keepalive_idle;int keepalive_intvl;
Greg Kroah-Hartman
maintainerPATCH 662/737 drm/amdgpu: Forward VMID reservation errors
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Natalie Vock <[email protected]>
[ Upstream commit 8defb4f081a5feccc3ea8372d0c7af3522124e1f ]
Otherwise userspace may be fooled into believing it has a reserved VMID when in reality it doesn't, ultimately leading to GPU hangs when SPM is used.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +4 -2
@@ -2496,10 +2496,12 @@ int amdgpu_vm_ioctl(struct drm_device *dcase AMDGPU_VM_OP_RESERVE_VMID :/* We only have requirement to reserve vmid from gfxhub */ if (!fpriv->vm.reserved_vmid[AMDGPU_GFXHUB (0 )]) { -amdgpu_vmid_alloc_reserved (adev,AMDGPU_GFXHUB (0 )); +int r =amdgpu_vmid_alloc_reserved (adev,AMDGPU_GFXHUB (0 )); + +if (r) +return r; fpriv->vm.reserved_vmid[AMDGPU_GFXHUB (0 )] = true; } -break ;case AMDGPU_VM_OP_UNRESERVE_VMID :if (fpriv->vm.reserved_vmid[AMDGPU_GFXHUB (0 )]) {
Greg Kroah-Hartman
maintainerPATCH 663/737 drm/mediatek: Fix probe memory leak
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
[ Upstream commit 5e49200593f331cd0629b5376fab9192f698e8ef ]
The Mediatek DRM driver allocates private data for components without a platform driver but as the lifetime is tied to each component device, the memory is never freed.
Tie the allocation lifetime to the DRM platform device so that the memory is released on probe failure (e.g. probe deferral) and when the driver is unbound.
--- drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c +1 -1
@@ -588,7 +588,7 @@ int mtk_ddp_comp_init(struct device_node type == MTK_DSI)return 0 ; - priv =devm_kzalloc (comp->dev,sizeof (*priv),GFP_KERNEL ); + priv =devm_kzalloc (dev,sizeof (*priv),GFP_KERNEL );if (!priv)return -ENOMEM ;
Greg Kroah-Hartman
maintainerPATCH 664/737 drm/mediatek: Fix probe resource leaks
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
[ Upstream commit 07c7c640a8eb9e196f357d15d88a59602a947197 ]
Make sure to unmap and release the component iomap and clock on probe failure (e.g. probe deferral) and on driver unbind.
Note that unlike of_iomap(), devm_of_iomap() also checks whether the region is already mapped.
--- drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 20 ++++++++++++++++---- drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 2 +- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 4 ++-- 3 files changed, 19 insertions(+), 7 deletions(-)
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c +16 -4
@@ -543,15 +543,20 @@ unsigned int mtk_drm_find_possible_crtc_return ret; } -int mtk_ddp_comp_init (struct device_node *node,struct mtk_ddp_comp *comp, +static void mtk_ddp_comp_clk_put (void *_clk) +{ +struct clk *clk = _clk; + +clk_put (clk); +} + +int mtk_ddp_comp_init (struct device *dev,struct device_node *node,struct mtk_ddp_comp *comp,unsigned int comp_id) {struct platform_device *comp_pdev;enum mtk_ddp_comp_type type;struct mtk_ddp_comp_dev *priv; -#if IS_REACHABLE (CONFIG_MTK_CMDQ )int ret; -#endif if (comp_id >=DDP_COMPONENT_DRM_ID_MAX )return -EINVAL ;
@@ -592,11 +597,18 @@ int mtk_ddp_comp_init(struct device_nodeif (!priv)return -ENOMEM ; - priv->regs =of_iomap (node,0 ); + priv->regs =devm_of_iomap (dev, node,0 ,NULL ); +if (IS_ERR (priv->regs)) +return PTR_ERR (priv->regs); + priv->clk =of_clk_get (node,0 );if (IS_ERR (priv->clk))return PTR_ERR (priv->clk); + ret =devm_add_action_or_reset (dev, mtk_ddp_comp_clk_put, priv->clk); +if (ret) +return ret; +#if IS_REACHABLE (CONFIG_MTK_CMDQ ) ret =cmdq_dev_get_client_reg (comp->dev, &priv->cmdq_reg,0 );if (ret)
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h +1 -1
@@ -279,7 +279,7 @@ int mtk_ddp_comp_get_id(struct device_no enum mtk_ddp_comp_type comp_type);unsigned int mtk_drm_find_possible_crtc_by_comp (struct drm_device *drm,struct device *dev); -int mtk_ddp_comp_init (struct device_node *comp_node,struct mtk_ddp_comp *comp, +int mtk_ddp_comp_init (struct device *dev,struct device_node *comp_node,struct mtk_ddp_comp *comp,unsigned int comp_id);enum mtk_ddp_comp_type mtk_ddp_comp_get_type (unsigned int comp_id); void mtk_ddp_write(struct cmdq_pkt *cmdq_pkt, unsigned int value,
drivers/gpu/drm/mediatek/mtk_drm_drv.c +2 -2
@@ -841,7 +841,7 @@ static int mtk_drm_probe(struct platform (void *)private->mmsys_dev, sizeof(*private->mmsys_dev)); private->ddp_comp[DDP_COMPONENT_DRM_OVL_ADAPTOR ].dev = &ovl_adaptor->dev; -mtk_ddp_comp_init (NULL , &private->ddp_comp[DDP_COMPONENT_DRM_OVL_ADAPTOR ], +mtk_ddp_comp_init (dev,NULL , &private->ddp_comp[DDP_COMPONENT_DRM_OVL_ADAPTOR ],DDP_COMPONENT_DRM_OVL_ADAPTOR );component_match_add (dev, &match, compare_dev, &ovl_adaptor->dev); }
@@ -910,7 +910,7 @@ static int mtk_drm_probe(struct platform node); } - ret =mtk_ddp_comp_init (node, &private->ddp_comp[comp_id], comp_id); + ret =mtk_ddp_comp_init (dev, node, &private->ddp_comp[comp_id], comp_id);if (ret) {of_node_put (node); goto err_node;
Greg Kroah-Hartman
maintainerPATCH 665/737 drm/tilcdc: request and mapp iomem with devres
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Philipp Stanner <[email protected]>
[ Upstream commit a196a5166e0812db267281c32fa0724fc5be6582 ]
tilcdc currently just ioremaps its iomem, without doing the (a bit more robust) request on the memory first. The devm_ functions provide a handy way to both request and ioremap the memory with automatic cleanup.
Replace the manual ioremap with the devm_ version.
Stable-dep-of: a585c7ef9cab ("drm/tilcdc: Fix removal actions in case of failed probe")
--- drivers/gpu/drm/tilcdc/tilcdc_drv.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-)
drivers/gpu/drm/tilcdc/tilcdc_drv.c +4 -15
@@ -182,9 +182,6 @@ static void tilcdc_fini(struct drm_devicif (priv->clk)clk_put (priv->clk); -if (priv->mmio) -iounmap (priv->mmio); -if (priv->wq)destroy_workqueue (priv->wq);
@@ -201,7 +198,6 @@ static int tilcdc_init(const struct drm_struct platform_device *pdev =to_platform_device (dev);struct device_node *node = dev->of_node;struct tilcdc_drm_private *priv; -struct resource *res;u32 bpp =0 ;int ret;
@@ -226,17 +222,10 @@ static int tilcdc_init(const struct drm_ goto init_failed; } - res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); -if (!res) { -dev_err (dev,"failed to get memory resource\n" ); - ret = -EINVAL ; - goto init_failed; - } - - priv->mmio =ioremap (res->start,resource_size (res)); -if (!priv->mmio) { -dev_err (dev,"failed to ioremap\n" ); - ret = -ENOMEM ; + priv->mmio =devm_platform_ioremap_resource (pdev,0 ); +if (IS_ERR (priv->mmio)) { +dev_err (dev,"failed to request / ioremap\n" ); + ret =PTR_ERR (priv->mmio); goto init_failed; }
Greg Kroah-Hartman
maintainerPATCH 666/737 drm/tilcdc: Fix removal actions in case of failed probe
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: "Kory Maincent (TI.com)" <[email protected]>
[ Upstream commit a585c7ef9cabda58088916baedc6573e9a5cd2a7 ]
The drm_kms_helper_poll_fini() and drm_atomic_helper_shutdown() helpers should only be called when the device has been successfully registered. Currently, these functions are called unconditionally in tilcdc_fini(), which causes warnings during probe deferral scenarios.
[ 7.972317] WARNING: CPU: 0 PID: 23 at drivers/gpu/drm/drm_atomic_state_helper.c:175 drm_atomic_helper_crtc_duplicate_state+0x60/0x68 ... [ 8.005820] drm_atomic_helper_crtc_duplicate_state from drm_atomic_get_crtc_state+0x68/0x108 [ 8.005858] drm_atomic_get_crtc_state from drm_atomic_helper_disable_all+0x90/0x1c8 [ 8.005885] drm_atomic_helper_disable_all from drm_atomic_helper_shutdown+0x90/0x144 [ 8.005911] drm_atomic_helper_shutdown from tilcdc_fini+0x68/0xf8 [tilcdc] [ 8.005957] tilcdc_fini [tilcdc] from tilcdc_pdev_probe+0xb0/0x6d4 [tilcdc]
Fix this by rewriting the failed probe cleanup path using the standard goto error handling pattern, which ensures that cleanup functions are only called on successfully initialized resources. Additionally, remove the now-unnecessary is_registered flag.
--- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 2 - drivers/gpu/drm/tilcdc/tilcdc_drv.c | 53 +++++++++++++++++++++++------------ drivers/gpu/drm/tilcdc/tilcdc_drv.h | 2 - 3 files changed, 37 insertions(+), 20 deletions(-)
drivers/gpu/drm/tilcdc/tilcdc_crtc.c +1 -1
@@ -586,7 +586,7 @@ out:drm_modeset_unlock (&crtc->mutex); } -static void tilcdc_crtc_destroy (struct drm_crtc *crtc) +void tilcdc_crtc_destroy (struct drm_crtc *crtc) {struct tilcdc_drm_private *priv = crtc->dev->dev_private;
drivers/gpu/drm/tilcdc/tilcdc_drv.c +35 -18
132 lines not on this page · raw message
drivers/gpu/drm/tilcdc/tilcdc_drv.h +1 -1
@@ -82,7 +82,6 @@ struct tilcdc_drm_private {struct drm_encoder *external_encoder;struct drm_connector *external_connector; -bool is_registered;bool is_componentized;bool irq_enabled; };
@@ -164,6 +163,7 @@ void tilcdc_crtc_set_panel_info(struct dvoid tilcdc_crtc_set_simulate_vesa_sync (struct drm_crtc *crtc,bool simulate_vesa_sync);void tilcdc_crtc_shutdown (struct drm_crtc *crtc); +void tilcdc_crtc_destroy (struct drm_crtc *crtc);int tilcdc_crtc_update_fb (struct drm_crtc *crtc,struct drm_framebuffer *fb,struct drm_pending_vblank_event *event);
Greg Kroah-Hartman
maintainerPATCH 667/737 tty: introduce and use tty_port_tty_vhangup() helper
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: "Jiri Slaby (SUSE)" <[email protected]>
[ Upstream commit 2b5eac0f8c6e79bc152c8804f9f88d16717013ab ]
This code (tty_get -> vhangup -> tty_put) is repeated on few places. Introduce a helper similar to tty_port_tty_hangup() (asynchronous) to handle even vhangup (synchronous).
And use it on those places.
In fact, reuse the tty_port_tty_hangup()'s code and call tty_vhangup() depending on a new bool parameter.
Stable-dep-of: 74098cc06e75 ("xhci: dbgtty: fix device unregister: fixup")
--- drivers/isdn/capi/capi.c | 8 +------- drivers/staging/greybus/uart.c | 7 +------ drivers/tty/serial/serial_core.c | 7 +------ drivers/tty/tty_port.c | 12 ++++++++---- drivers/usb/class/cdc-acm.c | 7 +------ drivers/usb/serial/usb-serial.c | 7 +------ include/linux/tty_port.h | 12 +++++++++++- net/bluetooth/rfcomm/tty.c | 7 +------ 8 files changed, 25 insertions(+), 42 deletions(-)
drivers/isdn/capi/capi.c +1 -7
@@ -304,15 +304,9 @@ static void capincci_alloc_minor(structstatic void capincci_free_minor (struct capincci *np) {struct capiminor *mp = np->minorp; -struct tty_struct *tty;if (mp) { - tty =tty_port_tty_get (&mp->port); -if (tty) { -tty_vhangup (tty); -tty_kref_put (tty); - } - +tty_port_tty_vhangup (&mp->port);capiminor_free (mp); } }
drivers/staging/greybus/uart.c +1 -6
@@ -914,7 +914,6 @@ static void gb_uart_remove(struct gbphy_ {struct gb_tty *gb_tty =gb_gbphy_get_data (gbphy_dev);struct gb_connection *connection = gb_tty->connection; -struct tty_struct *tty;int ret; ret =gbphy_runtime_get_sync (gbphy_dev);
@@ -927,11 +926,7 @@ static void gb_uart_remove(struct gbphy_wake_up_all (&gb_tty->wioctl);mutex_unlock (&gb_tty->mutex); - tty =tty_port_tty_get (&gb_tty->port); -if (tty) { -tty_vhangup (tty); -tty_kref_put (tty); - } +tty_port_tty_vhangup (&gb_tty->port);gb_connection_disable_rx (connection);tty_unregister_device (gb_tty_driver, gb_tty->minor);
drivers/tty/serial/serial_core.c +1 -6
@@ -3250,7 +3250,6 @@ static void serial_core_remove_one_port(struct uart_state *state = drv->state + uport->line;struct tty_port *port = &state->port;struct uart_port *uart_port; -struct tty_struct *tty;mutex_lock (&port->mutex); uart_port =uart_port_check (state);
@@ -3269,11 +3268,7 @@ static void serial_core_remove_one_port(*/ tty_port_unregister_device (port, drv->tty_driver, uport->line); - tty =tty_port_tty_get (port); -if (tty) { -tty_vhangup (port->tty); -tty_kref_put (tty); - } +tty_port_tty_vhangup (port);/* * If the port is used as a console, unregister it
drivers/tty/tty_port.c +8 -4
@@ -414,15 +414,19 @@ EXPORT_SYMBOL(tty_port_hangup);* @port: tty port * @check_clocal: hang only ttys with %CLOCAL unset? */ -void tty_port_tty_hangup (struct tty_port *port,bool check_clocal) +void __tty_port_tty_hangup (struct tty_port *port,bool check_clocal,bool async) {struct tty_struct *tty =tty_port_tty_get (port); -if (tty && (!check_clocal || !C_CLOCAL (tty))) -tty_hangup (tty); +if (tty && (!check_clocal || !C_CLOCAL (tty))) { +if (async) +tty_hangup (tty); +else +tty_vhangup (tty); + }tty_kref_put (tty); } -EXPORT_SYMBOL_GPL (tty_port_tty_hangup); +EXPORT_SYMBOL_GPL (__tty_port_tty_hangup);/** * tty_port_tty_wakeup - helper to wake up a tty
drivers/usb/class/cdc-acm.c +1 -6
@@ -1572,7 +1572,6 @@ err_put_port:static void acm_disconnect (struct usb_interface *intf) {struct acm *acm =usb_get_intfdata (intf); -struct tty_struct *tty;int i;/* sibling interface is already cleaning up */
@@ -1599,11 +1598,7 @@ static void acm_disconnect(struct usb_inusb_set_intfdata (acm->data,NULL );mutex_unlock (&acm->mutex); - tty =tty_port_tty_get (&acm->port); -if (tty) { -tty_vhangup (tty); -tty_kref_put (tty); - } +tty_port_tty_vhangup (&acm->port);cancel_delayed_work_sync (&acm->dwork);
drivers/usb/serial/usb-serial.c +1 -6
@@ -1178,7 +1178,6 @@ static void usb_serial_disconnect(structstruct usb_serial *serial =usb_get_intfdata (interface);struct device *dev = &interface->dev;struct usb_serial_port *port; -struct tty_struct *tty;/* sibling interface is cleaning up */ if (!serial)
@@ -1193,11 +1192,7 @@ static void usb_serial_disconnect(structfor (i =0 ; i < serial->num_ports; ++i) { port = serial->port[i]; - tty =tty_port_tty_get (&port->port); -if (tty) { -tty_vhangup (tty); -tty_kref_put (tty); - } +tty_port_tty_vhangup (&port->port);usb_serial_port_poison_urbs (port);wake_up_interruptible (&port->port.delta_msr_wait);cancel_work_sync (&port->work);
include/linux/tty_port.h +11 -1
@@ -235,7 +235,7 @@ bool tty_port_carrier_raised(struct tty_void tty_port_raise_dtr_rts (struct tty_port *port);void tty_port_lower_dtr_rts (struct tty_port *port);void tty_port_hangup (struct tty_port *port); -void tty_port_tty_hangup (struct tty_port *port,bool check_clocal); +void __tty_port_tty_hangup (struct tty_port *port,bool check_clocal,bool async);void tty_port_tty_wakeup (struct tty_port *port);int tty_port_block_til_ready (struct tty_port *port,struct tty_struct *tty,struct file *filp);
@@ -254,4 +254,14 @@ static inline int tty_port_users(struct return port->count + port->blocked_open; } +static inline void tty_port_tty_hangup (struct tty_port *port,bool check_clocal) +{ +__tty_port_tty_hangup (port, check_clocal, true); +} + +static inline void tty_port_tty_vhangup (struct tty_port *port) +{ +__tty_port_tty_hangup (port, false, false); +} +#endif
net/bluetooth/rfcomm/tty.c +1 -6
@@ -438,7 +438,6 @@ static int __rfcomm_release_dev(void __u {struct rfcomm_dev_req req;struct rfcomm_dev *dev; -struct tty_struct *tty;if (copy_from_user (&req, arg,sizeof (req)))return -EFAULT ;
@@ -464,11 +463,7 @@ static int __rfcomm_release_dev(void __urfcomm_dlc_close (dev->dlc,0 );/* Shut down TTY synchronously before freeing rfcomm_dev */ - tty =tty_port_tty_get (&dev->port); -if (tty) { -tty_vhangup (tty); -tty_kref_put (tty); - } +tty_port_tty_vhangup (&dev->port);if (!test_bit (RFCOMM_TTY_OWNED , &dev->status))tty_port_put (&dev->port);
Greg Kroah-Hartman
maintainerPATCH 668/737 xhci: dbgtty: fix device unregister: fixup
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Łukasz Bartosik <[email protected]>
[ Upstream commit 74098cc06e753d3ffd8398b040a3a1dfb65260c0 ]
This fixup replaces tty_vhangup() call with call to tty_port_tty_vhangup(). Both calls hangup tty device synchronously however tty_port_tty_vhangup() increases reference count during the hangup operation using scoped_guard(tty_port_tty).
--- drivers/usb/host/xhci-dbgtty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/host/xhci-dbgtty.c +1 -1
@@ -522,7 +522,7 @@ static void xhci_dbc_tty_unregister_devi* Hang up the TTY. This wakes up any blocked * writers and causes subsequent writes to fail. */ -tty_vhangup (port->port.tty); +tty_port_tty_vhangup (&port->port);tty_unregister_device (dbc_tty_driver, port->minor);xhci_dbc_tty_exit_port (port);
Greg Kroah-Hartman
maintainerPATCH 669/737 usb: xhci: move link chain bit quirk checks into one helper function.
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Niklas Neronin <[email protected]>
commit 7476a2215c07703db5e95efaa3fc5b9f957b9417 upstream.
Older 0.95 xHCI hosts and some other specific newer hosts require the chain bit to be set for Link TRBs even if the link TRB is not in the middle of a transfer descriptor (TD).
move the checks for all those cases into one xhci_link_chain_quirk() function to clean up and avoid code duplication.
No functional changes.
[skip renaming chain_links flag, reword commit message -Mathias]
--- drivers/usb/host/xhci-mem.c | 10 ++-------- drivers/usb/host/xhci-ring.c | 8 ++------ drivers/usb/host/xhci.h | 7 +++++-- 3 files changed, 9 insertions(+), 16 deletions(-)
drivers/usb/host/xhci-mem.c +2 -8
@@ -136,10 +136,7 @@ static void xhci_link_rings(struct xhci_if (!ring || !first || !last)return ; -/* Set chain bit for 0.95 hosts, and for isoc rings on AMD 0.96 host */ - chain_links = !!(xhci_link_trb_quirk (xhci) || - (ring->type ==TYPE_ISOC && - (xhci->quirks & XHCI_AMD_0x96_HOST))); + chain_links =xhci_link_chain_quirk (xhci, ring->type); next = ring->enq_seg->next;xhci_link_segments (ring->enq_seg, first, ring->type, chain_links);
@@ -330,10 +327,7 @@ static int xhci_alloc_segments_for_ring(unsigned int num =0 ;bool chain_links; -/* Set chain bit for 0.95 hosts, and for isoc rings on AMD 0.96 host */ - chain_links = !!(xhci_link_trb_quirk (xhci) || - (type ==TYPE_ISOC && - (xhci->quirks & XHCI_AMD_0x96_HOST))); + chain_links =xhci_link_chain_quirk (xhci, type); prev =xhci_segment_alloc (xhci, cycle_state, max_packet, num, flags);if (!prev)
drivers/usb/host/xhci-ring.c +2 -6
@@ -245,9 +245,7 @@ static void inc_enq(struct xhci_hcd *xhc* AMD 0.96 host, carry over the chain bit of the previous TRB * (which may mean the chain bit is cleared). */ -if (!(ring->type ==TYPE_ISOC && - (xhci->quirks & XHCI_AMD_0x96_HOST)) && - !xhci_link_trb_quirk (xhci)) { +if (!xhci_link_chain_quirk (xhci, ring->type)) { next->link.control &=cpu_to_le32 (~TRB_CHAIN ); next->link.control |=cpu_to_le32 (chain); }
@@ -3381,9 +3379,7 @@ static int prepare_ring(struct xhci_hcd/* If we're not dealing with 0.95 hardware or isoc rings * on AMD 0.96 host, clear the chain bit. */ -if (!xhci_link_trb_quirk (xhci) && - !(ep_ring->type ==TYPE_ISOC && - (xhci->quirks & XHCI_AMD_0x96_HOST))) +if (!xhci_link_chain_quirk (xhci, ep_ring->type)) ep_ring->enqueue->link.control &=cpu_to_le32 (~TRB_CHAIN );else
drivers/usb/host/xhci.h +5 -2
@@ -1784,9 +1784,12 @@ static inline void xhci_write_64(structlo_hi_writeq (val, regs); } -static inline int xhci_link_trb_quirk (struct xhci_hcd *xhci) + +/* Link TRB chain should always be set on 0.95 hosts, and AMD 0.96 ISOC rings */ +static inline bool xhci_link_chain_quirk (struct xhci_hcd *xhci,enum xhci_ring_type type) { -return xhci->quirks &XHCI_LINK_TRB_QUIRK ; +return (xhci->quirks &XHCI_LINK_TRB_QUIRK ) || + (type ==TYPE_ISOC && (xhci->quirks & XHCI_AMD_0x96_HOST)); }/* xHCI debugging */
Greg Kroah-Hartman
maintainerPATCH 670/737 usb: xhci: Apply the link chain quirk on NEC isoc endpoints
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michal Pecio <[email protected]>
commit bb0ba4cb1065e87f9cc75db1fa454e56d0894d01 upstream.
Two clearly different specimens of NEC uPD720200 (one with start/stop bug, one without) were seen to cause IOMMU faults after some Missed Service Errors. Faulting address is immediately after a transfer ring segment and patched dynamic debug messages revealed that the MSE was received when waiting for a TD near the end of that segment:
[ 1.041954] xhci_hcd: Miss service interval error for slot 1 ep 2 expected TD DMA ffa08fe0 [ 1.042120] xhci_hcd: AMD-Vi: Event logged [IO_PAGE_FAULT domain=0x0005 address=0xffa09000 flags=0x0000] [ 1.042146] xhci_hcd: AMD-Vi: Event logged [IO_PAGE_FAULT domain=0x0005 address=0xffa09040 flags=0x0000]
It gets even funnier if the next page is a ring segment accessible to the HC. Below, it reports MSE in segment at ff1e8000, plows through a zero-filled page at ff1e9000 and starts reporting events for TRBs in page at ff1ea000 every microframe, instead of jumping to seg ff1e6000.
[ 7.041671] xhci_hcd: Miss service interval error for slot 1 ep 2 expected TD DMA ff1e8fe0 [ 7.041999] xhci_hcd: Miss service interval error for slot 1 ep 2 expected TD DMA ff1e8fe0 [ 7.042011] xhci_hcd: WARN: buffer overrun event for slot 1 ep 2 on endpoint [ 7.042028] xhci_hcd: All TDs skipped for slot 1 ep 2. Clear skip flag. [ 7.042134] xhci_hcd: WARN: buffer overrun event for slot 1 ep 2 on endpoint [ 7.042138] xhci_hcd: ERROR Transfer event TRB DMA ptr not part of current TD ep_index 2 comp_code 31 [ 7.042144] xhci_hcd: Looking for event-dma 00000000ff1ea040 trb-start 00000000ff1e6820 trb-end 00000000ff1e6820 [ 7.042259] xhci_hcd: WARN: buffer overrun event for slot 1 ep 2 on endpoint [ 7.042262] xhci_hcd: ERROR Transfer event TRB DMA ptr not part of current TD ep_index 2 comp_code 31 [ 7.042266] xhci_hcd: Looking for event-dma 00000000ff1ea050 trb-start 00000000ff1e6820 trb-end 00000000ff1e6820
At some point completion events change from Isoch Buffer Overrun to Short Packet and the HC finally finds cycle bit mismatch in ff1ec000.
[ 7.098130] xhci_hcd: ERROR Transfer event TRB DMA ptr not part of current TD ep_index 2 comp_code 13 [ 7.098132] xhci_hcd: Looking for event-dma 00000000ff1ecc50 trb-start 00000000ff1e6820 trb-end 00000000ff1e6820 [ 7.098254] xhci_hcd: ERROR Transfer event TRB DMA ptr not part of current TD ep_index 2 comp_code 13 [ 7.098256] xhci_hcd: Looking for event-dma 00000000ff1ecc60 trb-start 00000000ff1e6820 trb-end 00000000ff1e6820 [ 7.098379] xhci_hcd: Overrun event on slot 1 ep 2
It's possible that data from the isochronous device were written to random buffers of pending TDs on other endpoints (either IN or OUT), other devices or even other HCs in the same IOMMU domain.
Lastly, an error from a different USB device on another HC. Was it caused by the above? I don't know, but it may have been. The disk was working without any other issues and generated PCIe traffic to starve the NEC of upstream BW and trigger those MSEs. The two HCs shared one x1 slot by means of a commercial "PCIe splitter" board.
[ 7.162604] usb 10-2: reset SuperSpeed USB device number 3 using xhci_hcd [ 7.178990] sd 9:0:0:0: [sdb] tag#0 UNKNOWN(0x2003) Result: hostbyte=0x07 driverbyte=DRIVER_OK cmd_age=0s [ 7.179001] sd 9:0:0:0: [sdb] tag#0 CDB: opcode=0x28 28 00 04 02 ae 00 00 02 00 00 [ 7.179004] I/O error, dev sdb, sector 67284480 op 0x0:(READ) flags 0x80700 phys_seg 5 prio class 0
Fortunately, it appears that this ridiculous bug is avoided by setting the chain bit of Link TRBs on isochronous rings. Other ancient HCs are known which also expect the bit to be set and they ignore Link TRBs if it's not. Reportedly, 0.95 spec guaranteed that the bit is set.
The bandwidth-starved NEC HC running a 32KB/uframe UVC endpoint reports tens of MSEs per second and runs into the bug within seconds. Chaining Link TRBs allows the same workload to run for many minutes, many times.
No negative side effects seen in UVC recording and UAC playback with a few devices at full speed, high speed and SuperSpeed.
The problem doesn't reproduce on the newer Renesas uPD720201/uPD720202 and on old Etron EJ168 and VIA VL805 (but the VL805 has other bug).
[shorten line length of log snippets in commit messge -Mathias]
--- drivers/usb/host/xhci.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
drivers/usb/host/xhci.h +11 -2
@@ -1785,11 +1785,20 @@ static inline void xhci_write_64(struct } -/* Link TRB chain should always be set on 0.95 hosts, and AMD 0.96 ISOC rings */ +/* +* Reportedly, some chapters of v0.95 spec said that Link TRB always has its chain bit set. +* Other chapters and later specs say that it should only be set if the link is inside a TD +* which continues from the end of one segment to the next segment. +* +* Some 0.95 hardware was found to misbehave if any link TRB doesn't have the chain bit set. +* +* 0.96 hardware from AMD and NEC was found to ignore unchained isochronous link TRBs when +* "resynchronizing the pipe" after a Missed Service Error. +*/ static inline bool xhci_link_chain_quirk (struct xhci_hcd *xhci,enum xhci_ring_type type) {return (xhci->quirks &XHCI_LINK_TRB_QUIRK ) || - (type ==TYPE_ISOC && (xhci->quirks & XHCI_AMD_0x96_HOST)); + (type ==TYPE_ISOC && (xhci->quirks & (XHCI_AMD_0x96_HOST |XHCI_NEC_HOST ))); }/* xHCI debugging */
Greg Kroah-Hartman
maintainerPATCH 671/737 net: Remove RTNL dance for SIOCBRADDIF and SIOCBRDELIF.
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thadeu Lima de Souza Cascardo <[email protected]>
commit ed3ba9b6e280e14cc3148c1b226ba453f02fa76c upstream.
SIOCBRDELIF is passed to dev_ioctl() first and later forwarded to br_ioctl_call(), which causes unnecessary RTNL dance and the splat below [0] under RTNL pressure.
Let's say Thread A is trying to detach a device from a bridge and Thread B is trying to remove the bridge.
In dev_ioctl(), Thread A bumps the bridge device's refcnt by netdev_hold() and releases RTNL because the following br_ioctl_call() also re-acquires RTNL.
In the race window, Thread B could acquire RTNL and try to remove the bridge device. Then, rtnl_unlock() by Thread B will release RTNL and wait for netdev_put() by Thread A.
Thread A, however, must hold RTNL after the unlock in dev_ifsioc(), which may take long under RTNL pressure, resulting in the splat by Thread B.
Thread A (SIOCBRDELIF) Thread B (SIOCBRDELBR)
---------------------- ----------------------
sock_ioctl sock_ioctl
`- sock_do_ioctl `- br_ioctl_call
`- dev_ioctl `- br_ioctl_stub
|- rtnl_lock |
|- dev_ifsioc '
' |- dev = __dev_get_by_name(...)
|- netdev_hold(dev, ...) .
/ |- rtnl_unlock ------. |
| |- br_ioctl_call `---> |- rtnl_lock
Race | | `- br_ioctl_stub |- br_del_bridge
Window | | | |- dev = __dev_get_by_name(...)
| | | May take long | `- br_dev_delete(dev, ...)
| | | under RTNL pressure | `- unregister_netdevice_queue(dev, ...)
| | | | `- rtnl_unlock
\ | |- rtnl_lock <-' `- netdev_run_todo
| |- ... `- netdev_run_todo
| `- rtnl_unlock |- __rtnl_unlock
| |- netdev_wait_allrefs_any
|- netdev_put(dev, ...) <----------------'Wait refcnt decrement and log splat below
To avoid blocking SIOCBRDELBR unnecessarily, let's not call dev_ioctl() for SIOCBRADDIF and SIOCBRDELIF.
In the dev_ioctl() path, we do the following:
1. Copy struct ifreq by get_user_ifreq in sock_do_ioctl()
2. Check CAP_NET_ADMIN in dev_ioctl()
3. Call dev_load() in dev_ioctl()
4. Fetch the master dev from ifr.ifr_name in dev_ifsioc()
3. can be done by request_module() in br_ioctl_call(), so we move 1., 2., and 4. to br_ioctl_stub().
Note that 2. is also checked later in add_del_if(), but it's better performed before RTNL.
SIOCBRADDIF and SIOCBRDELIF have been processed in dev_ioctl() since the pre-git era, and there seems to be no specific reason to process them there.
[0]:unregister_netdevice: waiting for wpan3 to become free. Usage count = 2ref_tracker: wpan3@ffff8880662d8608 has 1/1 users at
__netdev_tracker_alloc include/linux/netdevice.h:4282 [inline]
netdev_hold include/linux/netdevice.h:4311 [inline]
dev_ifsioc+0xc6a/0x1160 net/core/dev_ioctl.c:624
dev_ioctl+0x255/0x10c0 net/core/dev_ioctl.c:826
sock_do_ioctl+0x1ca/0x260 net/socket.c:1213
sock_ioctl+0x23a/0x6c0 net/socket.c:1318
vfs_ioctl fs/ioctl.c:51 [inline]
__do_sys_ioctl fs/ioctl.c:906 [inline]
__se_sys_ioctl fs/ioctl.c:892 [inline]
__x64_sys_ioctl+0x1a4/0x210 fs/ioctl.c:892
do_syscall_x64 arch/x86/entry/common.c:52 [inline]
do_syscall_64+0xcb/0x250 arch/x86/entry/common.c:83
entry_SYSCALL_64_after_hwframe+0x77/0x7f--- include/linux/if_bridge.h | 6 ++---- net/bridge/br_ioctl.c | 36 +++++++++++++++++++++++++++++++++--- net/bridge/br_private.h | 3 +-- net/core/dev_ioctl.c | 16 ---------------- net/socket.c | 19 +++++++++---------- 5 files changed, 45 insertions(+), 35 deletions(-)
include/linux/if_bridge.h +2 -4
@@ -65,11 +65,9 @@ struct br_ip_list {#define BR_DEFAULT_AGEING_TIME (300 * HZ)struct net_bridge ; -void brioctl_set (int (*hook)(struct net *net,struct net_bridge *br, -unsigned int cmd,struct ifreq *ifr, +void brioctl_set (int (*hook)(struct net *net,unsigned int cmd,void __user *uarg)); -int br_ioctl_call (struct net *net,struct net_bridge *br,unsigned int cmd, -struct ifreq *ifr,void __user *uarg); +int br_ioctl_call (struct net *net,unsigned int cmd,void __user *uarg);#if IS_ENABLED (CONFIG_BRIDGE ) &&IS_ENABLED (CONFIG_BRIDGE_IGMP_SNOOPING ) int br_multicast_list_adjacent(struct net_device *dev,
net/bridge/br_ioctl.c +33 -3
@@ -394,10 +394,26 @@ static int old_deviceless(struct net *nereturn -EOPNOTSUPP ; } -int br_ioctl_stub (struct net *net,struct net_bridge *br,unsigned int cmd, -struct ifreq *ifr,void __user *uarg) +int br_ioctl_stub (struct net *net,unsigned int cmd,void __user *uarg) {int ret = -EOPNOTSUPP ; +struct ifreq ifr; + +if (cmd ==SIOCBRADDIF || cmd ==SIOCBRDELIF ) { +void __user *data; +char *colon; + +if (!ns_capable (net->user_ns,CAP_NET_ADMIN )) +return -EPERM ; + +if (get_user_ifreq (&ifr, &data, uarg)) +return -EFAULT ; + + ifr.ifr_name[IFNAMSIZ -1 ] =0 ; + colon =strchr (ifr.ifr_name,':' ); +if (colon) + *colon =0 ; + }rtnl_lock ();
@@ -430,7 +446,21 @@ int br_ioctl_stub(struct net *net, strucbreak ;case SIOCBRADDIF :case SIOCBRDELIF : - ret =add_del_if (br, ifr->ifr_ifindex, cmd ==SIOCBRADDIF ); + { +struct net_device *dev; + + dev =__dev_get_by_name (net, ifr.ifr_name); +if (!dev || !netif_device_present (dev)) { + ret = -ENODEV ; +break ; + } +if (!netif_is_bridge_master (dev)) { + ret = -EOPNOTSUPP ; +break ; + } + + ret =add_del_if (netdev_priv (dev), ifr.ifr_ifindex, cmd ==SIOCBRADDIF ); + }break ; }
net/bridge/br_private.h +1 -2
@@ -948,8 +948,7 @@ br_port_get_check_rtnl(const struct net_/* br_ioctl.c */ int br_dev_siocdevprivate (struct net_device *dev,struct ifreq *rq,void __user *data,int cmd); -int br_ioctl_stub (struct net *net,struct net_bridge *br,unsigned int cmd, -struct ifreq *ifr,void __user *uarg); +int br_ioctl_stub (struct net *net,unsigned int cmd,void __user *uarg);/* br_multicast.c */ #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
net/core/dev_ioctl.c +0 -16
@@ -517,7 +517,6 @@ static int dev_ifsioc(struct net *net, sint err;struct net_device *dev =__dev_get_by_name (net, ifr->ifr_name);const struct net_device_ops *ops; -netdevice_tracker dev_tracker;if (!dev)return -ENODEV ;
@@ -580,19 +579,6 @@ static int dev_ifsioc(struct net *net, scase SIOCWANDEV :return dev_siocwandev (dev, &ifr->ifr_settings); -case SIOCBRADDIF : -case SIOCBRDELIF : -if (!netif_device_present (dev)) -return -ENODEV ; -if (!netif_is_bridge_master (dev)) -return -EOPNOTSUPP ; -netdev_hold (dev, &dev_tracker,GFP_KERNEL ); -rtnl_unlock (); - err =br_ioctl_call (net,netdev_priv (dev), cmd, ifr,NULL ); -netdev_put (dev, &dev_tracker); -rtnl_lock (); -return err; - case SIOCDEVPRIVATE ... SIOCDEVPRIVATE + 15:return dev_siocdevprivate (dev, ifr, data, cmd);
@@ -773,8 +759,6 @@ int dev_ioctl(struct net *net, unsignedcase SIOCBONDRELEASE :case SIOCBONDSETHWADDR :case SIOCBONDCHANGEACTIVE : -case SIOCBRADDIF : -case SIOCBRDELIF :case SIOCSHWTSTAMP :if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ;
net/socket.c +9 -10
@@ -1168,12 +1168,10 @@ static ssize_t sock_write_iter(struct ki*/ static DEFINE_MUTEX (br_ioctl_mutex); -static int (*br_ioctl_hook)(struct net *net,struct net_bridge *br, -unsigned int cmd,struct ifreq *ifr, +static int (*br_ioctl_hook)(struct net *net,unsigned int cmd,void __user *uarg); -void brioctl_set (int (*hook)(struct net *net,struct net_bridge *br, -unsigned int cmd,struct ifreq *ifr, +void brioctl_set (int (*hook)(struct net *net,unsigned int cmd,void __user *uarg)) {mutex_lock (&br_ioctl_mutex);
@@ -1182,8 +1180,7 @@ void brioctl_set(int (*hook)(struct net }EXPORT_SYMBOL (brioctl_set); -int br_ioctl_call (struct net *net,struct net_bridge *br,unsigned int cmd, -struct ifreq *ifr,void __user *uarg) +int br_ioctl_call (struct net *net,unsigned int cmd,void __user *uarg) {int err = -ENOPKG ;
@@ -1192,7 +1189,7 @@ int br_ioctl_call(struct net *net, strucmutex_lock (&br_ioctl_mutex);if (br_ioctl_hook) - err =br_ioctl_hook (net, br, cmd, ifr, uarg); + err =br_ioctl_hook (net, cmd, uarg);mutex_unlock (&br_ioctl_mutex);return err;
@@ -1292,7 +1289,9 @@ static long sock_ioctl(struct file *filecase SIOCSIFBR :case SIOCBRADDBR :case SIOCBRDELBR : - err =br_ioctl_call (net,NULL , cmd,NULL , argp); +case SIOCBRADDIF : +case SIOCBRDELIF : + err =br_ioctl_call (net, cmd, argp);break ;case SIOCGIFVLAN :case SIOCSIFVLAN :
@@ -3454,6 +3453,8 @@ static int compat_sock_ioctl_trans(struccase SIOCGPGRP :case SIOCBRADDBR :case SIOCBRDELBR : +case SIOCBRADDIF : +case SIOCBRDELIF :case SIOCGIFVLAN :case SIOCSIFVLAN :case SIOCGSKNS :
@@ -3493,8 +3494,6 @@ static int compat_sock_ioctl_trans(struccase SIOCGIFPFLAGS :case SIOCGIFTXQLEN :case SIOCSIFTXQLEN : -case SIOCBRADDIF : -case SIOCBRDELIF :case SIOCGIFNAME :case SIOCSIFNAME :case SIOCGMIIPHY :
Greg Kroah-Hartman
maintainerPATCH 672/737 drm/amd/display: Fix null pointer deref in dcn20_resource.c
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aurabindo Pillai <[email protected]>
[ Upstream commit ecbf60782662f0a388493685b85a645a0ba1613c ]
Fixes a hang thats triggered when MPV is run on a DCN401 dGPU:
mpv --hwdec=vaapi --vo=gpu --hwdec-codecs=all
and then enabling fullscreen playback (double click on the video)
The following calltrace will be seen:
[ 181.843989] BUG: kernel NULL pointer dereference, address: 0000000000000000 [ 181.843997] #PF: supervisor instruction fetch in kernel mode [ 181.844003] #PF: error_code(0x0010) - not-present page [ 181.844009] PGD 0 P4D 0 [ 181.844020] Oops: 0010 [#1] PREEMPT SMP NOPTI [ 181.844028] CPU: 6 PID: 1892 Comm: gnome-shell Tainted: G W OE 6.5.0-41-generic #41~22.04.2-Ubuntu [ 181.844038] Hardware name: System manufacturer System Product Name/CROSSHAIR VI HERO, BIOS 6302 10/23/2018 [ 181.844044] RIP: 0010:0x0 [ 181.844079] Code: Unable to access opcode bytes at 0xffffffffffffffd6. [ 181.844084] RSP: 0018:ffffb593c2b8f7b0 EFLAGS: 00010246 [ 181.844093] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000004 [ 181.844099] RDX: ffffb593c2b8f804 RSI: ffffb593c2b8f7e0 RDI: ffff9e3c8e758400 [ 181.844105] RBP: ffffb593c2b8f7b8 R08: ffffb593c2b8f9c8 R09: ffffb593c2b8f96c [ 181.844110] R10: 0000000000000000 R11: 0000000000000000 R12: ffffb593c2b8f9c8 [ 181.844115] R13: 0000000000000001 R14: ffff9e3c88000000 R15: 0000000000000005 [ 181.844121] FS: 00007c6e323bb5c0(0000) GS:ffff9e3f85f80000(0000) knlGS:0000000000000000 [ 181.844128] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 181.844134] CR2: ffffffffffffffd6 CR3: 0000000140fbe000 CR4: 00000000003506e0 [ 181.844141] Call Trace: [ 181.844146] <TASK> [ 181.844153] ? show_regs+0x6d/0x80 [ 181.844167] ? __die+0x24/0x80 [ 181.844179] ? page_fault_oops+0x99/0x1b0 [ 181.844192] ? do_user_addr_fault+0x31d/0x6b0 [ 181.844204] ? exc_page_fault+0x83/0x1b0 [ 181.844216] ? asm_exc_page_fault+0x27/0x30 [ 181.844237] dcn20_get_dcc_compression_cap+0x23/0x30 [amdgpu] [ 181.845115] amdgpu_dm_plane_validate_dcc.constprop.0+0xe5/0x180 [amdgpu] [ 181.845985] amdgpu_dm_plane_fill_plane_buffer_attributes+0x300/0x580 [amdgpu] [ 181.846848] fill_dc_plane_info_and_addr+0x258/0x350 [amdgpu] [ 181.847734] fill_dc_plane_attributes+0x162/0x350 [amdgpu] [ 181.848748] dm_update_plane_state.constprop.0+0x4e3/0x6b0 [amdgpu] [ 181.849791] ? dm_update_plane_state.constprop.0+0x4e3/0x6b0 [amdgpu] [ 181.850840] amdgpu_dm_atomic_check+0xdfe/0x1760 [amdgpu]
--- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +5 -4
@@ -2179,10 +2179,11 @@ bool dcn20_get_dcc_compression_cap(const const struct dc_dcc_surface_param *input, struct dc_surface_dcc_cap *output) { - return dc->res_pool->hubbub->funcs->get_dcc_compression_cap( - dc->res_pool->hubbub, -input , -output ); + if (dc->res_pool->hubbub->funcs->get_dcc_compression_cap) + return dc->res_pool->hubbub->funcs->get_dcc_compression_cap( + dc->res_pool->hubbub, input, output); + +return false; }static void dcn20_destroy_resource_pool (struct resource_pool **pool)
Greg Kroah-Hartman
maintainerPATCH 673/737 LoongArch: Refactor register restoration in ftrace_common_return
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chenghao Duan <[email protected]>
commit 45cb47c628dfbd1994c619f3eac271a780602826 upstream.
Refactor the register restoration sequence in the ftrace_common_return function to clearly distinguish between the logic of normal returns and direct call returns in function tracing scenarios. The logic is as follows:
1. In the case of a normal return, the execution flow returns to the traced function, and ftrace must ensure that the register data is consistent with the state when the function was entered.
ra = parent return address; t0 = traced function return address.
2. In the case of a direct call return, the execution flow jumps to the custom trampoline function, and ftrace must ensure that the register data is consistent with the state when ftrace was entered.
ra = traced function return address; t0 = parent return address.
--- arch/loongarch/kernel/mcount_dyn.S | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
arch/loongarch/kernel/mcount_dyn.S +10 -4
@@ -93,7 +93,6 @@ SYM_INNER_LABEL(ftrace_graph_call, SYM_L * at the callsite, so there is no need to restore the T series regs. */ ftrace_common_return: - PTR_L ra, sp, PT_R1 PTR_L a0, sp, PT_R4 PTR_L a1, sp, PT_R5 PTR_L a2, sp, PT_R6
@@ -103,12 +102,17 @@ ftrace_common_return: PTR_L a6, sp, PT_R10 PTR_L a7, sp, PT_R11 PTR_L fp, sp, PT_R22 - PTR_L t0, sp, PT_ERA PTR_L t1, sp, PT_R13 - PTR_ADDI sp, sp, PT_SIZE bnez t1, .Ldirect + + PTR_L ra, sp, PT_R1 + PTR_L t0, sp, PT_ERA + PTR_ADDI sp, sp, PT_SIZE jr t0 .Ldirect: + PTR_L t0, sp, PT_R1 + PTR_L ra, sp, PT_ERA + PTR_ADDI sp, sp, PT_SIZE jr t1 SYM_CODE_END(ftrace_common)
@@ -155,6 +159,8 @@ SYM_CODE_END(return_to_handler) #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS SYM_CODE_START(ftrace_stub_direct_tramp) - jr t0 + move t1, ra + move ra, t0 + jr t1 SYM_CODE_END(ftrace_stub_direct_tramp) #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
Greg Kroah-Hartman
maintainerPATCH 674/737 powerpc/64s/radix/kfence: map __kfence_pool at page granularity
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hari Bathini <[email protected]>
commit 353d7a84c214f184d5a6b62acdec8b4424159b7c upstream.
When KFENCE is enabled, total system memory is mapped at page level granularity. But in radix MMU mode, ~3GB additional memory is needed to map 100GB of system memory at page level granularity when compared to using 2MB direct mapping.This is not desired considering KFENCE is designed to be enabled in production kernels [1].
Mapping only the memory allocated for KFENCE pool at page granularity is sufficient to enable KFENCE support. So, allocate __kfence_pool during bootup and map it at page granularity instead of mapping all system memory at page granularity.
Without patch:
# cat /proc/meminfo MemTotal: 101201920 kB
With patch:
# cat /proc/meminfo MemTotal: 104483904 kB
Note that enabling KFENCE at runtime is disabled for radix MMU for now, as it depends on the ability to split page table mappings and such APIs are not currently implemented for radix MMU.
All kfence_test.c testcases passed with this patch.
[1] https://lore.kernel.org/all/[email protected]/
--- arch/powerpc/include/asm/kfence.h | 11 +++- arch/powerpc/mm/book3s64/radix_pgtable.c | 84 +++++++++++++++++++++++++++++-- arch/powerpc/mm/init-common.c | 3 + 3 files changed, 93 insertions(+), 5 deletions(-)
arch/powerpc/include/asm/kfence.h +10 -1
@@ -15,10 +15,19 @@#define ARCH_FUNC_PREFIX "."#endif +#ifdef CONFIG_KFENCE +extern bool kfence_disabled; + +static inline void disable_kfence (void ) +{ + kfence_disabled = true; +} +static inline bool arch_kfence_init_pool (void ) { -return true; +return !kfence_disabled; } +#endif #ifdef CONFIG_PPC64 static inline bool kfence_protect_page (unsigned long addr,bool protect)
arch/powerpc/mm/book3s64/radix_pgtable.c +80 -4
136 lines not on this page · raw message
arch/powerpc/mm/init-common.c +3 -0
@@ -31,6 +31,9 @@ EXPORT_SYMBOL_GPL(kernstart_virt_addr);bool disable_kuep = !IS_ENABLED (CONFIG_PPC_KUEP );bool disable_kuap = !IS_ENABLED (CONFIG_PPC_KUAP ); +#ifdef CONFIG_KFENCE +bool __ro_after_init kfence_disabled; +#endif static int __init parse_nosmep (char *p) {
Greg Kroah-Hartman
maintainerPATCH 675/737 ext4: fix error message when rejecting the default hash
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit a2187431c395cdfbf144e3536f25468c64fc7cfa ]
Commit 985b67cd8639 ("ext4: filesystems without casefold feature cannot be mounted with siphash") properly rejects volumes where s_def_hash_version is set to DX_HASH_SIPHASH, but the check and the error message should not look into casefold setup - a filesystem should never have DX_HASH_SIPHASH as the default hash. Fix it and, since we are there, move the check to ext4_hash_info_init.
be mounted with siphash")
[ The commit a2187431c395 intended to remove the if-block which was used
for an old SIPHASH rejection check. ]
--- fs/ext4/ext4.h | 1 + fs/ext4/super.c | 20 +++++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-)
fs/ext4/ext4.h +1 -0
@@ -2459,6 +2459,7 @@ static inline __le16 ext4_rec_len_to_dis#define DX_HASH_HALF_MD4_UNSIGNED 4#define DX_HASH_TEA_UNSIGNED 5#define DX_HASH_SIPHASH 6 +#define DX_HASH_LAST DX_HASH_SIPHASHstatic inline u32 ext4_chksum (struct ext4_sb_info *sbi,u32 crc,const void *address,unsigned int length)
fs/ext4/super.c +17 -3
@@ -5140,16 +5140,27 @@ out:return ret; } -static void ext4_hash_info_init (struct super_block *sb) +static int ext4_hash_info_init (struct super_block *sb) {struct ext4_sb_info *sbi =EXT4_SB (sb);struct ext4_super_block *es = sbi->s_es;unsigned int i; + sbi->s_def_hash_version = es->s_def_hash_version; + +if (sbi->s_def_hash_version >DX_HASH_LAST ) { +ext4_msg (sb,KERN_ERR , +"Invalid default hash set in the superblock" ); +return -EINVAL ; + }else if (sbi->s_def_hash_version ==DX_HASH_SIPHASH ) { +ext4_msg (sb,KERN_ERR , +"SIPHASH is not a valid default hash value" ); +return -EINVAL ; + } +for (i =0 ; i <4 ; i++) sbi->s_hash_seed[i] =le32_to_cpu (es->s_hash_seed[i]); - sbi->s_def_hash_version = es->s_def_hash_version;if (ext4_has_feature_dir_index (sb)) { i =le32_to_cpu (es->s_flags);if (i &EXT2_FLAGS_UNSIGNED_HASH )
@@ -5167,6 +5178,7 @@ static void ext4_hash_info_init(struct s#endif } } +return 0 ; }static int ext4_block_group_meta_init (struct super_block *sb,int silent)
@@ -5311,7 +5323,9 @@ static int __ext4_fill_super(struct fs_cif (err) goto failed_mount; -ext4_hash_info_init (sb); + err =ext4_hash_info_init (sb); +if (err) + goto failed_mount; err =ext4_handle_clustersize (sb);if (err)
Greg Kroah-Hartman
maintainerPATCH 676/737 ext4: introduce ITAIL helper
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ye Bin <[email protected]>
[ Upstream commit 69f3a3039b0d0003de008659cafd5a1eaaa0a7a4 ]
Introduce ITAIL helper to get the bound of xattr in inode.
--- fs/ext4/xattr.c | 10 +++++----- fs/ext4/xattr.h | 3 +++ 2 files changed, 8 insertions(+), 5 deletions(-)
fs/ext4/xattr.c +5 -5
@@ -653,7 +653,7 @@ ext4_xattr_ibody_get(struct inode *inodereturn error; raw_inode =ext4_raw_inode (&iloc); header =IHDR (inode, raw_inode); - end = (void *)raw_inode +EXT4_SB (inode->i_sb)->s_inode_size; + end =ITAIL (inode, raw_inode); error =xattr_check_inode (inode, header, end);if (error) goto cleanup;
@@ -797,7 +797,7 @@ ext4_xattr_ibody_list(struct dentry *denreturn error; raw_inode =ext4_raw_inode (&iloc); header =IHDR (inode, raw_inode); - end = (void *)raw_inode +EXT4_SB (inode->i_sb)->s_inode_size; + end =ITAIL (inode, raw_inode); error =xattr_check_inode (inode, header, end);if (error) goto cleanup;
@@ -883,7 +883,7 @@ int ext4_get_inode_usage(struct inode *i goto out; raw_inode =ext4_raw_inode (&iloc); header =IHDR (inode, raw_inode); - end = (void *)raw_inode +EXT4_SB (inode->i_sb)->s_inode_size; + end =ITAIL (inode, raw_inode); ret =xattr_check_inode (inode, header, end);if (ret) goto out;
@@ -2248,7 +2248,7 @@ int ext4_xattr_ibody_find(struct inode * header =IHDR (inode, raw_inode); is->s.base = is->s.first =IFIRST (header); is->s.here = is->s.first; - is->s.end = (void *)raw_inode +EXT4_SB (inode->i_sb)->s_inode_size; + is->s.end =ITAIL (inode, raw_inode);if (ext4_test_inode_state (inode,EXT4_STATE_XATTR )) { error =xattr_check_inode (inode, header, is->s.end);if (error)
@@ -2799,7 +2799,7 @@ retry:*/ base =IFIRST (header); - end = (void *)raw_inode +EXT4_SB (inode->i_sb)->s_inode_size; + end =ITAIL (inode, raw_inode); min_offs = end - base; total_ino =sizeof (struct ext4_xattr_ibody_header ) +sizeof (u32);
fs/ext4/xattr.h +3 -0
@@ -68,6 +68,9 @@ struct ext4_xattr_entry { ((void *)raw_inode + \ EXT4_GOOD_OLD_INODE_SIZE + \ EXT4_I(inode)->i_extra_isize)) +#define ITAIL (inode, raw_inode) \ + ((void *)(raw_inode) + \ + EXT4_SB((inode)->i_sb)->s_inode_size)#define IFIRST (hdr) ((struct ext4_xattr_entry *)((hdr)+1))/*
Greg Kroah-Hartman
maintainerPATCH 677/737 ext4: fix out-of-bound read in ext4_xattr_inode_dec_ref_all()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ye Bin <[email protected]>
[ Upstream commit 5701875f9609b000d91351eaa6bfd97fe2f157f4 ]
There's issue as follows:
BUG: KASAN: use-after-free in ext4_xattr_inode_dec_ref_all+0x6ff/0x790
Read of size 4 at addr ffff88807b003000 by task syz-executor.0/15172
CPU: 3 PID: 15172 Comm: syz-executor.0
Call Trace:
__dump_stack lib/dump_stack.c:82 [inline]
dump_stack+0xbe/0xfd lib/dump_stack.c:123
print_address_description.constprop.0+0x1e/0x280 mm/kasan/report.c:400
__kasan_report.cold+0x6c/0x84 mm/kasan/report.c:560
kasan_report+0x3a/0x50 mm/kasan/report.c:585
ext4_xattr_inode_dec_ref_all+0x6ff/0x790 fs/ext4/xattr.c:1137
ext4_xattr_delete_inode+0x4c7/0xda0 fs/ext4/xattr.c:2896
ext4_evict_inode+0xb3b/0x1670 fs/ext4/inode.c:323
evict+0x39f/0x880 fs/inode.c:622
iput_final fs/inode.c:1746 [inline]
iput fs/inode.c:1772 [inline]
iput+0x525/0x6c0 fs/inode.c:1758
ext4_orphan_cleanup fs/ext4/super.c:3298 [inline]
ext4_fill_super+0x8c57/0xba40 fs/ext4/super.c:5300
mount_bdev+0x355/0x410 fs/super.c:1446
legacy_get_tree+0xfe/0x220 fs/fs_context.c:611
vfs_get_tree+0x8d/0x2f0 fs/super.c:1576
do_new_mount fs/namespace.c:2983 [inline]
path_mount+0x119a/0x1ad0 fs/namespace.c:3316
do_mount+0xfc/0x110 fs/namespace.c:3329
__do_sys_mount fs/namespace.c:3540 [inline]
__se_sys_mount+0x219/0x2e0 fs/namespace.c:3514
do_syscall_64+0x33/0x40 arch/x86/entry/common.c:46
entry_SYSCALL_64_after_hwframe+0x67/0xd1
Memory state around the buggy address:
ffff88807b002f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ffff88807b002f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>ffff88807b003000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
^
ffff88807b003080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ffff88807b003100: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ffAbove issue happens as ext4_xattr_delete_inode() isn't check xattr is valid if xattr is in inode.
To solve above issue call xattr_check_inode() check if xattr if valid in inode. In fact, we can directly verify in ext4_iget_extra_inode(), so that there is no divergent verification.
--- fs/ext4/inode.c | 5 +++++ fs/ext4/xattr.c | 26 +------------------------- fs/ext4/xattr.h | 7 +++++++ 3 files changed, 13 insertions(+), 25 deletions(-)
fs/ext4/inode.c +5 -0
@@ -4728,6 +4728,11 @@ static inline int ext4_iget_extra_inode( *magic == cpu_to_le32(EXT4_XATTR_MAGIC)) {int err; + err =xattr_check_inode (inode,IHDR (inode, raw_inode), +ITAIL (inode, raw_inode)); +if (err) +return err; +ext4_set_inode_state (inode,EXT4_STATE_XATTR ); err =ext4_find_inline_data_nolock (inode);if (!err &&ext4_has_inline_data (inode))
fs/ext4/xattr.c +1 -25
@@ -312,7 +312,7 @@ __ext4_xattr_check_block(struct inode *i __ext4_xattr_check_block((inode), (bh), __func__, __LINE__) -static inline int +int __xattr_check_inode (struct inode *inode,struct ext4_xattr_ibody_header *header,void *end,const char *function,unsigned int line) {
@@ -320,9 +320,6 @@ __xattr_check_inode(struct inode *inode, function, line); } -#define xattr_check_inode (inode, header, end) \ - __xattr_check_inode((inode), (header), (end), __func__, __LINE__) -static int xattr_find_entry (struct inode *inode,struct ext4_xattr_entry **pentry,void *end,int name_index,const char *name,int sorted)
@@ -654,9 +651,6 @@ ext4_xattr_ibody_get(struct inode *inode raw_inode =ext4_raw_inode (&iloc); header =IHDR (inode, raw_inode); end =ITAIL (inode, raw_inode); - error =xattr_check_inode (inode, header, end); -if (error) - goto cleanup; entry =IFIRST (header); error =xattr_find_entry (inode, &entry, end, name_index, name,0 );if (error)
@@ -787,7 +781,6 @@ ext4_xattr_ibody_list(struct dentry *denstruct ext4_xattr_ibody_header *header;struct ext4_inode *raw_inode;struct ext4_iloc iloc; -void *end;int error;if (!ext4_test_inode_state (inode,EXT4_STATE_XATTR ))
@@ -797,14 +790,9 @@ ext4_xattr_ibody_list(struct dentry *denreturn error; raw_inode =ext4_raw_inode (&iloc); header =IHDR (inode, raw_inode); - end =ITAIL (inode, raw_inode); - error =xattr_check_inode (inode, header, end); -if (error) - goto cleanup; error =ext4_xattr_list_entries (dentry,IFIRST (header), buffer, buffer_size); -cleanup:brelse (iloc.bh);return error; }
@@ -872,7 +860,6 @@ int ext4_get_inode_usage(struct inode *istruct ext4_xattr_ibody_header *header;struct ext4_xattr_entry *entry;qsize_t ea_inode_refs =0 ; -void *end;int ret;lockdep_assert_held_read (&EXT4_I (inode)->xattr_sem);
@@ -883,10 +870,6 @@ int ext4_get_inode_usage(struct inode *i goto out; raw_inode =ext4_raw_inode (&iloc); header =IHDR (inode, raw_inode); - end =ITAIL (inode, raw_inode); - ret =xattr_check_inode (inode, header, end); -if (ret) - goto out;for (entry =IFIRST (header); !IS_LAST_ENTRY (entry); entry =EXT4_XATTR_NEXT (entry))
@@ -2250,9 +2233,6 @@ int ext4_xattr_ibody_find(struct inode * is->s.here = is->s.first; is->s.end =ITAIL (inode, raw_inode);if (ext4_test_inode_state (inode,EXT4_STATE_XATTR )) { - error =xattr_check_inode (inode, header, is->s.end); -if (error) -return error;/* Find the named attribute. */ error =xattr_find_entry (inode, &is->s.here, is->s.end, i->name_index, i->name,0 );
@@ -2803,10 +2783,6 @@ retry: min_offs = end - base; total_ino =sizeof (struct ext4_xattr_ibody_header ) +sizeof (u32); - error =xattr_check_inode (inode, header, end); -if (error) - goto cleanup; - ifree =ext4_xattr_free_space (base, &min_offs, base, &total_ino);if (ifree >= isize_diff) goto shift;
fs/ext4/xattr.h +7 -0
@@ -210,6 +210,13 @@ extern int ext4_xattr_ibody_set(handle_textern struct mb_cache *ext4_xattr_create_cache (void );extern void ext4_xattr_destroy_cache (struct mb_cache *); +extern int +__xattr_check_inode (struct inode *inode,struct ext4_xattr_ibody_header *header, +void *end,const char *function,unsigned int line); + +#define xattr_check_inode (inode, header, end) \ + __xattr_check_inode((inode), (header), (end), __func__, __LINE__) +#ifdef CONFIG_EXT4_FS_SECURITY extern int ext4_init_security (handle_t *handle,struct inode *inode,struct inode *dir,const struct qstr *qstr);
Greg Kroah-Hartman
maintainerPATCH 678/737 xfrm: state: fix out-of-bounds read during lookup
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit e952837f3ddb0ff726d5b582aa1aad9aa38d024d ]
lookup and resize can run in parallel.
The xfrm_state_hash_generation seqlock ensures a retry, but the hash functions can observe a hmask value that is too large for the new hlist array.
rehash does:
rcu_assign_pointer(net->xfrm.state_bydst, ndst) [..] net->xfrm.state_hmask = nhashmask;
While state lookup does:
h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, encap_family); hlist_for_each_entry_rcu(x, net->xfrm.state_bydst + h, bydst) {
This is only safe in case the update to state_bydst is larger than net->xfrm.xfrm_state_hmask (or if the lookup function gets serialized via state spinlock again).
Fix this by prefetching state_hmask and the associated pointers. The xfrm_state_hash_generation seqlock retry will ensure that the pointer and the hmask will be consistent.
The existing helpers, like xfrm_dst_hash(), are now unsafe for RCU side, add lockdep assertions to document that they are only safe for insert side.
xfrm_state_lookup_byaddr() uses the spinlock rather than RCU. AFAICS this is an oversight from back when state lookup was converted to RCU, this lock should be replaced with RCU in a future patch.
--- net/xfrm/xfrm_state.c | 84 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 18 deletions(-)
net/xfrm/xfrm_state.c +66 -18
@@ -34,6 +34,8 @@#define xfrm_state_deref_prot (table, net) \ rcu_dereference_protected((table), lockdep_is_held(&(net)->xfrm.xfrm_state_lock)) +#define xfrm_state_deref_check (table, net) \ + rcu_dereference_check((table), lockdep_is_held(&(net)->xfrm.xfrm_state_lock))static void xfrm_state_gc_task (struct work_struct *work);
@@ -62,6 +64,8 @@ static inline unsigned int xfrm_dst_hash u32 reqid, unsigned short family) { +lockdep_assert_held (&net->xfrm.xfrm_state_lock); +return __xfrm_dst_hash (daddr, saddr, reqid, family, net->xfrm.state_hmask); }
@@ -70,6 +74,8 @@ static inline unsigned int xfrm_src_hashconst xfrm_address_t *saddr, unsigned short family) { + lockdep_assert_held(&net->xfrm.xfrm_state_lock); +return __xfrm_src_hash (daddr, saddr, family, net->xfrm.state_hmask); }
@@ -77,11 +83,15 @@ static inline unsigned int xfrm_spi_hash(struct net *net, const xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family) { + lockdep_assert_held(&net->xfrm.xfrm_state_lock); +return __xfrm_spi_hash (daddr, spi, proto, family, net->xfrm.state_hmask); }static unsigned int xfrm_seq_hash (struct net *net,u32 seq) { +lockdep_assert_held (&net->xfrm.xfrm_state_lock); +return __xfrm_seq_hash (seq, net->xfrm.state_hmask); }
@@ -1025,16 +1035,38 @@ xfrm_init_tempstate(struct xfrm_state *x x->props.family = tmpl->encap_family; } -static struct xfrm_state *__xfrm_state_lookup_all (struct net *net,u32 mark, +struct xfrm_hash_state_ptrs { +const struct hlist_head *bydst; +const struct hlist_head *bysrc; +const struct hlist_head *byspi; +unsigned int hmask; +}; + +static void xfrm_hash_ptrs_get (const struct net *net,struct xfrm_hash_state_ptrs *ptrs) +{ +unsigned int sequence; + +do { + sequence =read_seqcount_begin (&net->xfrm.xfrm_state_hash_generation); + + ptrs->bydst =xfrm_state_deref_check (net->xfrm.state_bydst, net); + ptrs->bysrc =xfrm_state_deref_check (net->xfrm.state_bysrc, net); + ptrs->byspi =xfrm_state_deref_check (net->xfrm.state_byspi, net); + ptrs->hmask = net->xfrm.state_hmask; + }while (read_seqcount_retry (&net->xfrm.xfrm_state_hash_generation, sequence)); +} + +static struct xfrm_state *__xfrm_state_lookup_all (const struct xfrm_hash_state_ptrs *state_ptrs, +u32 mark,const xfrm_address_t *daddr,__be32 spi,u8 proto,unsigned short family,struct xfrm_dev_offload *xdo) { -unsigned int h =xfrm_spi_hash (net, daddr, spi, proto, family); +unsigned int h =__xfrm_spi_hash (daddr, spi, proto, family, state_ptrs->hmask);struct xfrm_state *x; -hlist_for_each_entry_rcu (x, net->xfrm.state_byspi + h, byspi) { +hlist_for_each_entry_rcu (x, state_ptrs->byspi + h, byspi) {#ifdef CONFIG_XFRM_OFFLOAD if (xdo->type ==XFRM_DEV_OFFLOAD_PACKET ) {if (x->xso.type !=XFRM_DEV_OFFLOAD_PACKET )
@@ -1068,15 +1100,16 @@ static struct xfrm_state *__xfrm_state_lreturn NULL ; } -static struct xfrm_state *__xfrm_state_lookup (struct net *net,u32 mark, +static struct xfrm_state *__xfrm_state_lookup (const struct xfrm_hash_state_ptrs *state_ptrs, +u32 mark,const xfrm_address_t *daddr,__be32 spi,u8 proto,unsigned short family) { -unsigned int h =xfrm_spi_hash (net, daddr, spi, proto, family); +unsigned int h =__xfrm_spi_hash (daddr, spi, proto, family, state_ptrs->hmask);struct xfrm_state *x; -hlist_for_each_entry_rcu (x, net->xfrm.state_byspi + h, byspi) { +hlist_for_each_entry_rcu (x, state_ptrs->byspi + h, byspi) { if (x->props.family != family || x->id.spi != spi || x->id.proto != proto ||
@@ -1093,15 +1126,16 @@ static struct xfrm_state *__xfrm_state_lreturn NULL ; } -static struct xfrm_state *__xfrm_state_lookup_byaddr (struct net *net,u32 mark, +static struct xfrm_state *__xfrm_state_lookup_byaddr (const struct xfrm_hash_state_ptrs *state_ptrs, +u32 mark,const xfrm_address_t *daddr,const xfrm_address_t *saddr,u8 proto,unsigned short family) { -unsigned int h =xfrm_src_hash (net, daddr, saddr, family); +unsigned int h =__xfrm_src_hash (daddr, saddr, family, state_ptrs->hmask);struct xfrm_state *x; -hlist_for_each_entry_rcu (x, net->xfrm.state_bysrc + h, bysrc) { +hlist_for_each_entry_rcu (x, state_ptrs->bysrc + h, bysrc) { if (x->props.family != family || x->id.proto != proto || !xfrm_addr_equal(&x->id.daddr, daddr, family) ||
@@ -1121,14 +1155,17 @@ static struct xfrm_state *__xfrm_state_lstatic inline struct xfrm_state *__xfrm_state_locate (struct xfrm_state *x,int use_spi,int family) { +struct xfrm_hash_state_ptrs state_ptrs;struct net *net =xs_net (x);u32 mark = x->mark.v & x->mark.m; +xfrm_hash_ptrs_get (net, &state_ptrs); +if (use_spi) -return __xfrm_state_lookup (net, mark, &x->id.daddr, +return __xfrm_state_lookup (&state_ptrs, mark, &x->id.daddr, x->id.spi, x->id.proto, family);else -return __xfrm_state_lookup_byaddr (net, mark, +return __xfrm_state_lookup_byaddr (&state_ptrs, mark, &x->id.daddr, &x->props.saddr, x->id.proto, family);
@@ -1191,6 +1228,7 @@ xfrm_state_find(const xfrm_address_t *da unsigned short family, u32 if_id) {static xfrm_address_t saddr_wildcard = { }; +struct xfrm_hash_state_ptrs state_ptrs;struct net *net =xp_net (pol);unsigned int h, h_wildcard;struct xfrm_state *x, *x0, *to_put;
@@ -1207,8 +1245,10 @@ xfrm_state_find(const xfrm_address_t *da sequence =read_seqcount_begin (&net->xfrm.xfrm_state_hash_generation);rcu_read_lock (); - h =xfrm_dst_hash (net, daddr, saddr, tmpl->reqid, encap_family); -hlist_for_each_entry_rcu (x, net->xfrm.state_bydst + h, bydst) { +xfrm_hash_ptrs_get (net, &state_ptrs); + + h =__xfrm_dst_hash (daddr, saddr, tmpl->reqid, encap_family, state_ptrs.hmask); +hlist_for_each_entry_rcu (x, state_ptrs.bydst + h, bydst) {#ifdef CONFIG_XFRM_OFFLOAD if (pol->xdo.type ==XFRM_DEV_OFFLOAD_PACKET ) {if (x->xso.type !=XFRM_DEV_OFFLOAD_PACKET )
@@ -1241,8 +1281,9 @@ xfrm_state_find(const xfrm_address_t *daif (best || acquire_in_progress) goto found; - h_wildcard =xfrm_dst_hash (net, daddr, &saddr_wildcard, tmpl->reqid, encap_family); -hlist_for_each_entry_rcu (x, net->xfrm.state_bydst + h_wildcard, bydst) { + h_wildcard =__xfrm_dst_hash (daddr, &saddr_wildcard, tmpl->reqid, + encap_family, state_ptrs.hmask); +hlist_for_each_entry_rcu (x, state_ptrs.bydst + h_wildcard, bydst) {#ifdef CONFIG_XFRM_OFFLOAD if (pol->xdo.type ==XFRM_DEV_OFFLOAD_PACKET ) {if (x->xso.type !=XFRM_DEV_OFFLOAD_PACKET )
@@ -1277,7 +1318,7 @@ found: x = best;if (!x && !error && !acquire_in_progress) {if (tmpl->id.spi && - (x0 =__xfrm_state_lookup_all (net, mark, daddr, + (x0 =__xfrm_state_lookup_all (&state_ptrs, mark, daddr, tmpl->id.spi, tmpl->id.proto, encap_family, &pol->xdo)) !=NULL ) {
@@ -2032,10 +2073,13 @@ struct xfrm_state * xfrm_state_lookup(struct net *net, u32 mark, const xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family) { + struct xfrm_hash_state_ptrs state_ptrs;struct xfrm_state *x;rcu_read_lock (); - x =__xfrm_state_lookup (net, mark, daddr, spi, proto, family); +xfrm_hash_ptrs_get (net, &state_ptrs); + + x =__xfrm_state_lookup (&state_ptrs, mark, daddr, spi, proto, family);rcu_read_unlock ();return x; }
@@ -2046,10 +2090,14 @@ xfrm_state_lookup_byaddr(struct net *net const xfrm_address_t *daddr, const xfrm_address_t *saddr, u8 proto, unsigned short family) { + struct xfrm_hash_state_ptrs state_ptrs;struct xfrm_state *x;spin_lock_bh (&net->xfrm.xfrm_state_lock); - x =__xfrm_state_lookup_byaddr (net, mark, daddr, saddr, proto, family); + +xfrm_hash_ptrs_get (net, &state_ptrs); + + x =__xfrm_state_lookup_byaddr (&state_ptrs, mark, daddr, saddr, proto, family);spin_unlock_bh (&net->xfrm.xfrm_state_lock);return x; }
Greg Kroah-Hartman
maintainerPATCH 679/737 page_pool: Fix use-after-free in page_pool_recycle_in_ring
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dong Chenchen <[email protected]>
[ Upstream commit 271683bb2cf32e5126c592b5d5e6a756fa374fd9 ]
syzbot reported a uaf in page_pool_recycle_in_ring:
BUG: KASAN: slab-use-after-free in lock_release+0x151/0xa30 kernel/locking/lockdep.c:5862 Read of size 8 at addr ffff8880286045a0 by task syz.0.284/6943 CPU: 0 UID: 0 PID: 6943 Comm: syz.0.284 Not tainted 6.13.0-rc3-syzkaller-gdfa94ce54f41 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024 Call Trace: <TASK> __dump_stack lib/dump_stack.c:94 [inline] dump_stack_lvl+0x241/0x360 lib/dump_stack.c:120 print_address_description mm/kasan/report.c:378 [inline] print_report+0x169/0x550 mm/kasan/report.c:489 kasan_report+0x143/0x180 mm/kasan/report.c:602 lock_release+0x151/0xa30 kernel/locking/lockdep.c:5862 __raw_spin_unlock_bh include/linux/spinlock_api_smp.h:165 [inline] _raw_spin_unlock_bh+0x1b/0x40 kernel/locking/spinlock.c:210 spin_unlock_bh include/linux/spinlock.h:396 [inline] ptr_ring_produce_bh include/linux/ptr_ring.h:164 [inline] page_pool_recycle_in_ring net/core/page_pool.c:707 [inline] page_pool_put_unrefed_netmem+0x748/0xb00 net/core/page_pool.c:826 page_pool_put_netmem include/net/page_pool/helpers.h:323 [inline] page_pool_put_full_netmem include/net/page_pool/helpers.h:353 [inline] napi_pp_put_page+0x149/0x2b0 net/core/skbuff.c:1036 skb_pp_recycle net/core/skbuff.c:1047 [inline] skb_free_head net/core/skbuff.c:1094 [inline] skb_release_data+0x6c4/0x8a0 net/core/skbuff.c:1125 skb_release_all net/core/skbuff.c:1190 [inline] __kfree_skb net/core/skbuff.c:1204 [inline] sk_skb_reason_drop+0x1c9/0x380 net/core/skbuff.c:1242 kfree_skb_reason include/linux/skbuff.h:1263 [inline] __skb_queue_purge_reason include/linux/skbuff.h:3343 [inline]
root cause is:
page_pool_recycle_in_ring
ptr_ring_produce
spin_lock(&r->producer_lock);
WRITE_ONCE(r->queue[r->producer++], ptr)
//recycle last page to pool
page_pool_release
page_pool_scrub
page_pool_empty_ring
ptr_ring_consume
page_pool_return_page //release all page
__page_pool_destroy
free_percpu(pool->recycle_stats);
free(pool) //free
spin_unlock(&r->producer_lock); //pool->ring uaf read recycle_stat_inc(pool, ring);
page_pool can be free while page pool recycle the last page in ring. Add producer-lock barrier to page_pool_release to prevent the page pool from being free before all pages have been recycled.
recycle_stat_inc() is empty when CONFIG_PAGE_POOL_STATS is not enabled, which will trigger Wempty-body build warning. Add definition for pool stat macro to fix warning.
--- net/core/page_pool.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-)
net/core/page_pool.c +14 -13
@@ -140,9 +140,9 @@ u64 *page_pool_ethtool_stats_get(u64 *daEXPORT_SYMBOL (page_pool_ethtool_stats_get);#else -#define alloc_stat_inc (pool, __stat) -#define recycle_stat_inc (pool, __stat) -#define recycle_stat_add (pool, __stat, val) +#define alloc_stat_inc (...) do { } while (0) +#define recycle_stat_inc (...) do { } while (0) +#define recycle_stat_add (...) do { } while (0)#endif static bool page_pool_producer_lock (struct page_pool *pool)
@@ -549,19 +549,16 @@ skip_dma_unmap:static bool page_pool_recycle_in_ring (struct page_pool *pool,struct page *page) { -int ret; -/* BH protection not needed if current is softirq */ -if (in_softirq ()) - ret =ptr_ring_produce (&pool->ring, page); -else - ret =ptr_ring_produce_bh (&pool->ring, page); +bool in_softirq, ret; -if (!ret) { +/* BH protection not needed if current is softirq */ + in_softirq =page_pool_producer_lock (pool); + ret = !__ptr_ring_produce (&pool->ring, page); +if (ret)recycle_stat_inc (pool, ring); -return true; - } +page_pool_producer_unlock (pool, in_softirq); -return false; +return ret; }/* Only allow direct recycling in special circumstances, into the
@@ -850,10 +847,14 @@ static void page_pool_scrub(struct page_static int page_pool_release (struct page_pool *pool) { +bool in_softirq;int inflight;page_pool_scrub (pool); inflight =page_pool_inflight (pool); +/* Acquire producer lock to make sure producers have exited. */ + in_softirq =page_pool_producer_lock (pool); +page_pool_producer_unlock (pool, in_softirq);if (!inflight)page_pool_free (pool);
Greg Kroah-Hartman
maintainerPATCH 680/737 net: dsa: sja1105: fix kasan out-of-bounds warning in sja1105_table_delete_entry()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vladimir Oltean <[email protected]>
[ Upstream commit 5f2b28b79d2d1946ee36ad8b3dc0066f73c90481 ]
There are actually 2 problems:
- deleting the last element doesn't require the memmove of elements [i + 1, end) over it. Actually, element i+1 is out of bounds.
- The memmove itself should move size - i - 1 elements, because the last element is out of bounds.
The out-of-bounds element still remains out of bounds after being accessed, so the problem is only that we touch it, not that it becomes in active use. But I suppose it can lead to issues if the out-of-bounds element is part of an unmapped page.
--- drivers/net/dsa/sja1105/sja1105_static_config.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/net/dsa/sja1105/sja1105_static_config.c +4 -2
@@ -1921,8 +1921,10 @@ int sja1105_table_delete_entry(struct sjif (i > table->entry_count)return -ERANGE ; -memmove (entries + i * entry_size, entries + (i +1 ) * entry_size, - (table->entry_count - i) * entry_size); +if (i +1 < table->entry_count) { +memmove (entries + i * entry_size, entries + (i +1 ) * entry_size, + (table->entry_count - i -1 ) * entry_size); + } table->entry_count--;
Greg Kroah-Hartman
maintainerPATCH 681/737 mm: fix arithmetic for bdi min_ratio
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jingbo Xu <[email protected]>
commit e0646b7590084a5bf3b056d3ad871d9379d2c25a upstream.
Since now bdi->min_ratio is part per million, fix the wrong arithmetic. Otherwise it will fail with -EINVAL when setting a reasonable min_ratio, as it tries to set min_ratio to (min_ratio * BDI_RATIO_SCALE) in percentage unit, which exceeds 100% anyway.
# cat /sys/class/bdi/253\:0/min_ratio
0
# cat /sys/class/bdi/253\:0/max_ratio
100
# echo 1 > /sys/class/bdi/253\:0/min_ratio
-bash: echo: write error: Invalid argument--- mm/page-writeback.c | 1 - 1 file changed, 1 deletion(-)
mm/page-writeback.c +0 -1
@@ -714,7 +714,6 @@ static int __bdi_set_min_ratio(struct baif (min_ratio >100 *BDI_RATIO_SCALE )return -EINVAL ; - min_ratio *=BDI_RATIO_SCALE ;spin_lock_bh (&bdi_lock);if (min_ratio > bdi->max_ratio) {
Greg Kroah-Hartman
maintainerPATCH 682/737 mm: fix arithmetic for max_prop_frac when setting max_ratio
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jingbo Xu <[email protected]>
commit fa151a39a6879144b587f35c0dfcc15e1be9450f upstream.
Since now bdi->max_ratio is part per million, fix the wrong arithmetic for max_prop_frac when setting max_ratio. Otherwise the miscalculated max_prop_frac will affect the incrementing of writeout completion count when max_ratio is not 100%.
--- mm/page-writeback.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
mm/page-writeback.c +2 -1
@@ -750,7 +750,8 @@ static int __bdi_set_max_ratio(struct ba ret = -EINVAL ; }else { bdi->max_ratio = max_ratio; - bdi->max_prop_frac = (FPROP_FRAC_BASE * max_ratio) /100 ; + bdi->max_prop_frac = (FPROP_FRAC_BASE * max_ratio) / + (100 *BDI_RATIO_SCALE ); }spin_unlock_bh (&bdi_lock);
Greg Kroah-Hartman
maintainerPATCH 683/737 genirq/irq_sim: Initialize work context pointers properly
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gyeyoung Baek <[email protected]>
[ Upstream commit 8a2277a3c9e4cc5398f80821afe7ecbe9bdf2819 ]
Initialize ops member's pointers properly by using kzalloc() instead of kmalloc() when allocating the simulation work context. Otherwise the pointers contain random content leading to invalid dereferencing.
[ The context change is due to the commit 011f583781fa ("genirq/irq_sim: add an extended irq_sim initializer") which is irrelevant to the logic of this patch. ]
--- kernel/irq/irq_sim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/irq/irq_sim.c +1 -1
@@ -166,7 +166,7 @@ struct irq_domain *irq_domain_create_sim {struct irq_sim_work_ctx *work_ctx; - work_ctx =kmalloc (sizeof (*work_ctx),GFP_KERNEL ); + work_ctx =kzalloc (sizeof (*work_ctx),GFP_KERNEL );if (!work_ctx) goto err_out;
Greg Kroah-Hartman
maintainerPATCH 684/737 f2fs: remove unused GC_FAILURE_PIN
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chao Yu <[email protected]>
[ Upstream commit 968c4f72b23c0c8f1e94e942eab89b8c5a3022e7 ]
After commit 3db1de0e582c ("f2fs: change the current atomic write way"), we removed all GC_FAILURE_ATOMIC usage, let's change i_gc_failures[] array to i_pin_failure for cleanup.
Meanwhile, let's define i_current_depth and i_gc_failures as union variable due to they won't be valid at the same time.
Stable-dep-of: 10b591e7fb7c ("f2fs: fix to avoid updating compression context during writeback")
--- fs/f2fs/f2fs.h | 14 +++++--------- fs/f2fs/file.c | 12 +++++------- fs/f2fs/inode.c | 6 ++---- fs/f2fs/recovery.c | 3 +-- 4 files changed, 13 insertions(+), 22 deletions(-)
fs/f2fs/f2fs.h +5 -9
@@ -762,11 +762,6 @@ enum {#define DEF_DIR_LEVEL 0 -enum { -GC_FAILURE_PIN , -MAX_GC_FAILURE -}; -/* used for f2fs_inode_info->flags */ enum {FI_NEW_INODE ,/* indicate newly allocated inode */
@@ -814,9 +809,10 @@ struct f2fs_inode_info {unsigned long i_flags;/* keep an inode flags for ioctl */ unsigned char i_advise;/* use to give file attribute hints */ unsigned char i_dir_level;/* use for dentry level for large dir */ -unsigned int i_current_depth;/* only for directory depth */ -/* for gc failure statistic */ -unsigned int i_gc_failures[MAX_GC_FAILURE ]; +union { +unsigned int i_current_depth;/* only for directory depth */ +unsigned int i_gc_failures;/* for gc failure statistic */ + };unsigned int i_pino;/* parent inode number */ umode_t i_acl_mode;/* keep file acl mode temporarily */
@@ -3173,7 +3169,7 @@ static inline void f2fs_i_depth_write(ststatic inline void f2fs_i_gc_failures_write (struct inode *inode,unsigned int count) { -F2FS_I (inode)->i_gc_failures[GC_FAILURE_PIN ] = count; +F2FS_I (inode)->i_gc_failures = count;f2fs_mark_inode_dirty_sync (inode, true); }
fs/f2fs/file.c +5 -7
@@ -3329,13 +3329,11 @@ int f2fs_pin_file_control(struct inode */* Use i_gc_failures for normal file as a risk signal. */ if (inc) -f2fs_i_gc_failures_write (inode, - fi->i_gc_failures[GC_FAILURE_PIN ] +1 ); +f2fs_i_gc_failures_write (inode, fi->i_gc_failures +1 ); -if (fi->i_gc_failures[GC_FAILURE_PIN ] > sbi->gc_pin_file_threshold) { +if (fi->i_gc_failures > sbi->gc_pin_file_threshold) {f2fs_warn (sbi,"%s: Enable GC = ino %lx after %x GC trials" , - __func__, inode->i_ino, - fi->i_gc_failures[GC_FAILURE_PIN ]); + __func__, inode->i_ino, fi->i_gc_failures);clear_inode_flag (inode,FI_PIN_FILE );return -EAGAIN ; }
@@ -3404,7 +3402,7 @@ static int f2fs_ioc_set_pin_file(struct }set_inode_flag (inode,FI_PIN_FILE ); - ret =F2FS_I (inode)->i_gc_failures[GC_FAILURE_PIN ]; + ret =F2FS_I (inode)->i_gc_failures; done:f2fs_update_time (sbi,REQ_TIME ); out:
@@ -3419,7 +3417,7 @@ static int f2fs_ioc_get_pin_file(struct__u32 pin =0 ;if (is_inode_flag_set (inode,FI_PIN_FILE )) - pin =F2FS_I (inode)->i_gc_failures[GC_FAILURE_PIN ]; + pin =F2FS_I (inode)->i_gc_failures;return put_user (pin, (u32 __user *)arg); }
fs/f2fs/inode.c +2 -4
@@ -428,8 +428,7 @@ static int do_read_inode(struct inode *iif (S_ISDIR (inode->i_mode)) fi->i_current_depth =le32_to_cpu (ri->i_current_depth);else if (S_ISREG (inode->i_mode)) - fi->i_gc_failures[GC_FAILURE_PIN ] = -le16_to_cpu (ri->i_gc_failures); + fi->i_gc_failures =le16_to_cpu (ri->i_gc_failures); fi->i_xattr_nid =le32_to_cpu (ri->i_xattr_nid); fi->i_flags =le32_to_cpu (ri->i_flags);if (S_ISREG (inode->i_mode))
@@ -691,8 +690,7 @@ void f2fs_update_inode(struct inode *ino ri->i_current_depth =cpu_to_le32 (F2FS_I (inode)->i_current_depth); else if (S_ISREG(inode->i_mode)) - ri->i_gc_failures = -cpu_to_le16 (F2FS_I (inode)->i_gc_failures[GC_FAILURE_PIN ]); + ri->i_gc_failures = cpu_to_le16(F2FS_I(inode)->i_gc_failures); ri->i_xattr_nid =cpu_to_le32 (F2FS_I (inode)->i_xattr_nid); ri->i_flags =cpu_to_le32 (F2FS_I (inode)->i_flags); ri->i_pino =cpu_to_le32 (F2FS_I (inode)->i_pino);
fs/f2fs/recovery.c +1 -2
@@ -330,8 +330,7 @@ static int recover_inode(struct inode *iF2FS_I (inode)->i_advise = raw->i_advise;F2FS_I (inode)->i_flags =le32_to_cpu (raw->i_flags);f2fs_set_inode_flags (inode); -F2FS_I (inode)->i_gc_failures[GC_FAILURE_PIN ] = -le16_to_cpu (raw->i_gc_failures); +F2FS_I (inode)->i_gc_failures =le16_to_cpu (raw->i_gc_failures);recover_inline_flags (inode, raw);
Greg Kroah-Hartman
maintainerPATCH 685/737 f2fs: keep POSIX_FADV_NOREUSE ranges
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jaegeuk Kim <[email protected]>
[ Upstream commit ef0c333cad8d1940f132a7ce15f15920216a3bd5 ]
This patch records POSIX_FADV_NOREUSE ranges for users to reclaim the caches instantly off from LRU.
Stable-dep-of: 10b591e7fb7c ("f2fs: fix to avoid updating compression context during writeback")
--- fs/f2fs/debug.c | 3 ++ fs/f2fs/f2fs.h | 12 ++++++++++- fs/f2fs/file.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++----- fs/f2fs/inode.c | 14 +++++++++++++ fs/f2fs/super.c | 1 5 files changed, 84 insertions(+), 6 deletions(-)
fs/f2fs/debug.c +3 -0
@@ -100,6 +100,7 @@ static void update_general_status(struct si->ndirty_imeta =get_pages (sbi,F2FS_DIRTY_IMETA ); si->ndirty_dirs = sbi->ndirty_inode[DIR_INODE ]; si->ndirty_files = sbi->ndirty_inode[FILE_INODE ]; + si->ndonate_files = sbi->donate_files; si->nquota_files = sbi->nquota_files; si->ndirty_all = sbi->ndirty_inode[DIRTY_META ]; si->aw_cnt =atomic_read (&sbi->atomic_files);
@@ -436,6 +437,8 @@ static int stat_show(struct seq_file *s, si->compr_inode, si->compr_blocks);seq_printf (s," - Swapfile Inode: %u\n" , si->swapfile_inode); +seq_printf (s," - Donate Inode: %u\n" , + si->ndonate_files);seq_printf (s," - Orphan/Append/Update Inode: %u, %u, %u\n" , si->orphans, si->append, si->update); seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n",
fs/f2fs/f2fs.h +11 -1
@@ -837,6 +837,11 @@ struct f2fs_inode_info {#endif struct list_head dirty_list;/* dirty list for dirs and files */ struct list_head gdirty_list;/* linked in global dirty list */ + +/* linked in global inode list for cache donation */ +struct list_head gdonate_list; +pgoff_t donate_start, donate_end;/* inclusive */ +struct task_struct *atomic_write_task;/* store atomic write task */ struct extent_tree *extent_tree[NR_EXTENT_CACHES ];/* cached extent_tree entry */
@@ -1261,6 +1266,7 @@ enum inode_type {DIR_INODE ,/* for dirty dir inode */ FILE_INODE ,/* for dirty regular/symlink inode */ DIRTY_META ,/* for all dirtied inode metadata */ +DONATE_INODE ,/* for all inode to donate pages */ NR_INODE_TYPE, };
@@ -1613,6 +1619,9 @@ struct f2fs_sb_info {unsigned int warm_data_age_threshold;unsigned int last_age_weight; +/* control donate caches */ +unsigned int donate_files; +/* basic filesystem units */ unsigned int log_sectors_per_block;/* log2 sectors per block */ unsigned int log_blocksize;/* log2 block size */
@@ -3948,7 +3957,8 @@ struct f2fs_stat_info {unsigned long long allocated_data_blocks;int ndirty_node, ndirty_dent, ndirty_meta, ndirty_imeta;int ndirty_data, ndirty_qdata; -unsigned int ndirty_dirs, ndirty_files, nquota_files, ndirty_all; +unsigned int ndirty_dirs, ndirty_files, ndirty_all; +unsigned int nquota_files, ndonate_files;int nats, dirty_nats, sits, dirty_sits;int free_nids, avail_nids, alloc_nids;int total_count, utilization;
fs/f2fs/file.c +55 -5
73 lines not on this page · raw message
fs/f2fs/inode.c +14 -0
@@ -811,6 +811,19 @@ int f2fs_write_inode(struct inode *inodereturn 0 ; } +static void f2fs_remove_donate_inode (struct inode *inode) +{ +struct f2fs_sb_info *sbi =F2FS_I_SB (inode); + +if (list_empty (&F2FS_I (inode)->gdonate_list)) +return ; + +spin_lock (&sbi->inode_lock[DONATE_INODE ]); +list_del_init (&F2FS_I (inode)->gdonate_list); + sbi->donate_files--; +spin_unlock (&sbi->inode_lock[DONATE_INODE ]); +} +/* * Called at the last iput() if i_nlink is zero */
@@ -844,6 +857,7 @@ void f2fs_evict_inode(struct inode *inodf2fs_bug_on (sbi,get_dirty_pages (inode));f2fs_remove_dirty_inode (inode); +f2fs_remove_donate_inode (inode);f2fs_destroy_extent_tree (inode);
fs/f2fs/super.c +1 -0
@@ -1413,6 +1413,7 @@ static struct inode *f2fs_alloc_inode(stspin_lock_init (&fi->i_size_lock);INIT_LIST_HEAD (&fi->dirty_list);INIT_LIST_HEAD (&fi->gdirty_list); +INIT_LIST_HEAD (&fi->gdonate_list);init_f2fs_rwsem (&fi->i_gc_rwsem[READ ]);init_f2fs_rwsem (&fi->i_gc_rwsem[WRITE ]);init_f2fs_rwsem (&fi->i_xattr_sem);
Greg Kroah-Hartman
maintainerPATCH 686/737 f2fs: drop inode from the donation list when the last file is closed
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jaegeuk Kim <[email protected]>
[ Upstream commit 078cad8212ce4f4ebbafcc0936475b8215e1ca2a ]
Let's drop the inode from the donation list when there is no other open file.
Stable-dep-of: 10b591e7fb7c ("f2fs: fix to avoid updating compression context during writeback")
--- fs/f2fs/f2fs.h | 2 ++ fs/f2fs/file.c | 8 +++++++- fs/f2fs/inode.c | 2 +- fs/f2fs/super.c | 1 + 4 files changed, 11 insertions(+), 2 deletions(-)
fs/f2fs/f2fs.h +2 -0
@@ -841,6 +841,7 @@ struct f2fs_inode_info {/* linked in global inode list for cache donation */ struct list_head gdonate_list;pgoff_t donate_start, donate_end;/* inclusive */ +atomic_t open_count;/* # of open files */ struct task_struct *atomic_write_task;/* store atomic write task */ struct extent_tree *extent_tree[NR_EXTENT_CACHES ];
@@ -3560,6 +3561,7 @@ int f2fs_try_to_free_nats(struct f2fs_sbvoid f2fs_update_inode (struct inode *inode,struct page *node_page);void f2fs_update_inode_page (struct inode *inode);int f2fs_write_inode (struct inode *inode,struct writeback_control *wbc); +void f2fs_remove_donate_inode (struct inode *inode);void f2fs_evict_inode (struct inode *inode);void f2fs_handle_failed_inode (struct inode *inode);
fs/f2fs/file.c +7 -1
@@ -621,7 +621,10 @@ static int f2fs_file_open(struct inode *if (err)return err; -return finish_preallocate_blocks (inode); + err =finish_preallocate_blocks (inode); +if (!err) +atomic_inc (&F2FS_I (inode)->open_count); +return err; }void f2fs_truncate_data_blocks_range (struct dnode_of_data *dn,int count)
@@ -1966,6 +1969,9 @@ out:static int f2fs_release_file (struct inode *inode,struct file *filp) { +if (atomic_dec_and_test (&F2FS_I (inode)->open_count)) +f2fs_remove_donate_inode (inode); +/* * f2fs_release_file is called at every close calls. So we should * not drop any inmemory pages by close called by other process.
fs/f2fs/inode.c +1 -1
@@ -811,7 +811,7 @@ int f2fs_write_inode(struct inode *inodereturn 0 ; } -static void f2fs_remove_donate_inode (struct inode *inode) +void f2fs_remove_donate_inode (struct inode *inode) {struct f2fs_sb_info *sbi =F2FS_I_SB (inode);
fs/f2fs/super.c +1 -0
@@ -1409,6 +1409,7 @@ static struct inode *f2fs_alloc_inode(st/* Initialize f2fs-specific inode info */ atomic_set (&fi->dirty_pages,0 );atomic_set (&fi->i_compr_blocks,0 ); +atomic_set (&fi->open_count,0 );init_f2fs_rwsem (&fi->i_sem);spin_lock_init (&fi->i_size_lock);INIT_LIST_HEAD (&fi->dirty_list);
Greg Kroah-Hartman
maintainerPATCH 687/737 f2fs: fix to avoid updating compression context during writeback
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chao Yu <[email protected]>
[ Upstream commit 10b591e7fb7cdc8c1e53e9c000dc0ef7069aaa76 ]
Bai, Shuangpeng <[email protected]> reported a bug as below:
Oops: divide error: 0000 [#1] SMP KASAN PTI CPU: 0 UID: 0 PID: 11441 Comm: syz.0.46 Not tainted 6.17.0 #1 PREEMPT(full) Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014 RIP: 0010:f2fs_all_cluster_page_ready+0x106/0x550 fs/f2fs/compress.c:857 Call Trace: <TASK> f2fs_write_cache_pages fs/f2fs/data.c:3078 [inline] __f2fs_write_data_pages fs/f2fs/data.c:3290 [inline] f2fs_write_data_pages+0x1c19/0x3600 fs/f2fs/data.c:3317 do_writepages+0x38e/0x640 mm/page-writeback.c:2634 filemap_fdatawrite_wbc mm/filemap.c:386 [inline] __filemap_fdatawrite_range mm/filemap.c:419 [inline] file_write_and_wait_range+0x2ba/0x3e0 mm/filemap.c:794 f2fs_do_sync_file+0x6e6/0x1b00 fs/f2fs/file.c:294 generic_write_sync include/linux/fs.h:3043 [inline] f2fs_file_write_iter+0x76e/0x2700 fs/f2fs/file.c:5259 new_sync_write fs/read_write.c:593 [inline] vfs_write+0x7e9/0xe00 fs/read_write.c:686 ksys_write+0x19d/0x2d0 fs/read_write.c:738 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xf7/0x470 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f
The bug was triggered w/ below race condition:
fsync setattr ioctl
- f2fs_do_sync_file
- file_write_and_wait_range
- f2fs_write_cache_pages
: inode is non-compressed
: cc.cluster_size =
F2FS_I(inode)->i_cluster_size = 0
- tag_pages_for_writeback
- f2fs_setattr
- truncate_setsize
- f2fs_truncate
- f2fs_fileattr_set
- f2fs_setflags_common
- set_compress_context
: F2FS_I(inode)->i_cluster_size = 4 : set_inode_flag(inode, FI_COMPRESSED_FILE)
- f2fs_compressed_file
: return true
- f2fs_all_cluster_page_ready
: "pgidx % cc->cluster_size" trigger dividing 0 issue
Let's change as below to fix this issue:
- introduce a new atomic type variable .writeback in structure f2fs_inode_info to track the number of threads which calling f2fs_write_cache_pages().
- use .i_sem lock to protect .writeback update.
- check .writeback before update compression context in f2fs_setflags_common() to avoid race w/ ->writepages.
--- fs/f2fs/data.c | 17 +++++++++++++++++ fs/f2fs/f2fs.h | 3 ++- fs/f2fs/file.c | 5 +++-- fs/f2fs/super.c | 1 + 4 files changed, 23 insertions(+), 3 deletions(-)
fs/f2fs/data.c +17 -0
@@ -3233,6 +3233,19 @@ static inline bool __should_serialize_ioreturn false; } +static inline void account_writeback (struct inode *inode,bool inc) +{ +if (!f2fs_sb_has_compression (F2FS_I_SB (inode))) +return ; + +f2fs_down_read (&F2FS_I (inode)->i_sem); +if (inc) +atomic_inc (&F2FS_I (inode)->writeback); +else +atomic_dec (&F2FS_I (inode)->writeback); +f2fs_up_read (&F2FS_I (inode)->i_sem); +} +static int __f2fs_write_data_pages (struct address_space *mapping,struct writeback_control *wbc,enum iostat_type io_type)
@@ -3282,10 +3295,14 @@ static int __f2fs_write_data_pages(struc locked = true; } +account_writeback (inode, true); +blk_start_plug (&plug); ret =f2fs_write_cache_pages (mapping, wbc, io_type);blk_finish_plug (&plug); +account_writeback (inode, false); +if (locked)mutex_unlock (&sbi->writepages);
fs/f2fs/f2fs.h +2 -1
@@ -869,6 +869,7 @@ struct f2fs_inode_info {unsigned char i_compress_level;/* compress level (lz4hc,zstd) */ unsigned char i_compress_flag;/* compress flag */ unsigned int i_cluster_size;/* cluster size */ +atomic_t writeback;/* count # of writeback thread */ unsigned int atomic_write_cnt;loff_t original_i_size;/* original i_size before atomic write */
@@ -4485,7 +4486,7 @@ static inline bool f2fs_disable_compressf2fs_up_write (&F2FS_I (inode)->i_sem);return true; } -if (f2fs_is_mmap_file (inode) || +if (f2fs_is_mmap_file (inode) ||atomic_read (&fi->writeback) || (S_ISREG (inode->i_mode) &&F2FS_HAS_BLOCKS (inode))) {f2fs_up_write (&F2FS_I (inode)->i_sem);return false;
fs/f2fs/file.c +3 -2
@@ -2045,8 +2045,9 @@ static int f2fs_setflags_common(struct if2fs_down_write (&F2FS_I (inode)->i_sem);if (!f2fs_may_compress (inode) || - (S_ISREG (inode->i_mode) && -F2FS_HAS_BLOCKS (inode))) { +atomic_read (&fi->writeback) || + (S_ISREG (inode->i_mode) && +F2FS_HAS_BLOCKS (inode))) {f2fs_up_write (&F2FS_I (inode)->i_sem);return -EINVAL ; }
fs/f2fs/super.c +1 -0
@@ -1410,6 +1410,7 @@ static struct inode *f2fs_alloc_inode(statomic_set (&fi->dirty_pages,0 );atomic_set (&fi->i_compr_blocks,0 );atomic_set (&fi->open_count,0 ); +atomic_set (&fi->writeback,0 );init_f2fs_rwsem (&fi->i_sem);spin_lock_init (&fi->i_size_lock);INIT_LIST_HEAD (&fi->dirty_list);
Greg Kroah-Hartman
maintainerPATCH 688/737 f2fs: fix to propagate error from f2fs_enable_checkpoint()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chao Yu <[email protected]>
[ Upstream commit be112e7449a6e1b54aa9feac618825d154b3a5c7 ]
In order to let userspace detect such error rather than suffering silent failure.
--- fs/f2fs/super.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-)
fs/f2fs/super.c +15 -9
@@ -2267,9 +2267,10 @@ restore_flag:return err; } -static void f2fs_enable_checkpoint (struct f2fs_sb_info *sbi) +static int f2fs_enable_checkpoint (struct f2fs_sb_info *sbi) {int retry =DEFAULT_RETRY_IO_COUNT ; +int ret;/* we should flush all the data to keep data consistency */ do {
@@ -2287,10 +2288,14 @@ static void f2fs_enable_checkpoint(strucset_sbi_flag (sbi,SBI_IS_DIRTY );f2fs_up_write (&sbi->gc_lock); -f2fs_sync_fs (sbi->sb,1 ); + ret =f2fs_sync_fs (sbi->sb,1 ); +if (ret) +f2fs_err (sbi,"%s sync_fs failed, ret: %d" , __func__, ret);/* Let's ensure there's no pending checkpoint anymore */ f2fs_flush_ckpt_thread (sbi); + +return ret; }static int f2fs_remount (struct super_block *sb,int *flags,char *data)
@@ -2511,7 +2516,9 @@ static int f2fs_remount(struct super_bloif (err) goto restore_discard; }else { -f2fs_enable_checkpoint (sbi); + err =f2fs_enable_checkpoint (sbi); +if (err) + goto restore_discard; } }
@@ -4689,13 +4696,12 @@ reset_checkpoint:/* f2fs_recover_fsync_data() cleared this already */ clear_sbi_flag (sbi,SBI_POR_DOING ); -if (test_opt (sbi,DISABLE_CHECKPOINT )) { +if (test_opt (sbi,DISABLE_CHECKPOINT )) err =f2fs_disable_checkpoint (sbi); -if (err) - goto sync_free_meta; - }else if (is_set_ckpt_flags (sbi,CP_DISABLED_FLAG )) { -f2fs_enable_checkpoint (sbi); - } +else if (is_set_ckpt_flags (sbi,CP_DISABLED_FLAG )) + err =f2fs_enable_checkpoint (sbi); +if (err) + goto sync_free_meta;/* * If filesystem is not mounted as read-only then
Greg Kroah-Hartman
maintainerPATCH 689/737 f2fs: use global inline_xattr_slab instead of per-sb slab cache
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chao Yu <[email protected]>
[ Upstream commit 1f27ef42bb0b7c0740c5616ec577ec188b8a1d05 ]
As Hong Yun reported in mailing list:
loop7: detected capacity change from 0 to 131072
------------[ cut here ]------------ kmem_cache of name 'f2fs_xattr_entry-7:7' already exists WARNING: CPU: 0 PID: 24426 at mm/slab_common.c:110 kmem_cache_sanity_check mm/slab_common.c:109 [inline] WARNING: CPU: 0 PID: 24426 at mm/slab_common.c:110 __kmem_cache_create_args+0xa6/0x320 mm/slab_common.c:307 CPU: 0 UID: 0 PID: 24426 Comm: syz.7.1370 Not tainted 6.17.0-rc4 #1 PREEMPT(full) Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014 RIP: 0010:kmem_cache_sanity_check mm/slab_common.c:109 [inline] RIP: 0010:__kmem_cache_create_args+0xa6/0x320 mm/slab_common.c:307 Call Trace: __kmem_cache_create include/linux/slab.h:353 [inline] f2fs_kmem_cache_create fs/f2fs/f2fs.h:2943 [inline] f2fs_init_xattr_caches+0xa5/0xe0 fs/f2fs/xattr.c:843 f2fs_fill_super+0x1645/0x2620 fs/f2fs/super.c:4918 get_tree_bdev_flags+0x1fb/0x260 fs/super.c:1692 vfs_get_tree+0x43/0x140 fs/super.c:1815 do_new_mount+0x201/0x550 fs/namespace.c:3808 do_mount fs/namespace.c:4136 [inline] __do_sys_mount fs/namespace.c:4347 [inline] __se_sys_mount+0x298/0x2f0 fs/namespace.c:4324 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0x8e/0x3a0 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x76/0x7e
The bug can be reproduced w/ below scripts:
- mount /dev/vdb /mnt1
- mount /dev/vdc /mnt2
- umount /mnt1
- mounnt /dev/vdb /mnt1
The reason is if we created two slab caches, named f2fs_xattr_entry-7:3 and f2fs_xattr_entry-7:7, and they have the same slab size. Actually, slab system will only create one slab cache core structure which has slab name of "f2fs_xattr_entry-7:3", and two slab caches share the same structure and cache address.
So, if we destroy f2fs_xattr_entry-7:3 cache w/ cache address, it will decrease reference count of slab cache, rather than release slab cache entirely, since there is one more user has referenced the cache.
Then, if we try to create slab cache w/ name "f2fs_xattr_entry-7:3" again, slab system will find that there is existed cache which has the same name and trigger the warning.
Let's changes to use global inline_xattr_slab instead of per-sb slab cache for fixing.
--- fs/f2fs/f2fs.h | 3 --- fs/f2fs/super.c | 17 ++++++++--------- fs/f2fs/xattr.c | 30 ++++++++++-------------------- fs/f2fs/xattr.h | 10 ++++++---- 4 files changed, 24 insertions(+), 36 deletions(-)
fs/f2fs/f2fs.h +0 -3
@@ -1778,9 +1778,6 @@ struct f2fs_sb_info {spinlock_t error_lock;/* protect errors/stop_reason array */ bool error_dirty;/* errors of sb is dirty */ -struct kmem_cache *inline_xattr_slab;/* inline xattr entry */ -unsigned int inline_xattr_slab_size;/* default inline xattr slab size */ -/* For reclaimed segs statistics per each GC mode */ unsigned int gc_segment_mode;/* GC state for reclaimed segments */ unsigned int gc_reclaimed_segs[MAX_GC_MODE ];/* Reclaimed segs for each mode */
fs/f2fs/super.c +8 -9
@@ -1683,7 +1683,6 @@ static void f2fs_put_super(struct super_destroy_device_list (sbi);f2fs_destroy_page_array_cache (sbi); -f2fs_destroy_xattr_caches (sbi);#ifdef CONFIG_QUOTA for (i =0 ; i <MAXQUOTAS ; i++)kfree (F2FS_OPTION (sbi).s_qf_names[i]);
@@ -4464,13 +4463,9 @@ try_onemore:if (err) goto free_iostat; -/* init per sbi slab cache */ - err =f2fs_init_xattr_caches (sbi); -if (err) - goto free_percpu; err =f2fs_init_page_array_cache (sbi);if (err) - goto free_xattr_cache; + goto free_percpu;/* get an inode for meta space */ sbi->meta_inode =f2fs_iget (sb,F2FS_META_INO (sbi));
@@ -4787,8 +4782,6 @@ free_meta_inode: sbi->meta_inode =NULL ; free_page_array_cache:f2fs_destroy_page_array_cache (sbi); -free_xattr_cache: -f2fs_destroy_xattr_caches (sbi); free_percpu:destroy_percpu_info (sbi); free_iostat:
@@ -4949,10 +4942,15 @@ static int __init init_f2fs_fs(void) err =f2fs_create_casefold_cache ();if (err) goto free_compress_cache; - err =register_filesystem (&f2fs_fs_type); + err =f2fs_init_xattr_cache ();if (err) goto free_casefold_cache; + err =register_filesystem (&f2fs_fs_type); +if (err) + goto free_xattr_cache;return 0 ; +free_xattr_cache: +f2fs_destroy_xattr_cache (); free_casefold_cache:f2fs_destroy_casefold_cache (); free_compress_cache:
@@ -4993,6 +4991,7 @@ fail: static void __exit exit_f2fs_fs(void) {unregister_filesystem (&f2fs_fs_type); +f2fs_destroy_xattr_cache ();f2fs_destroy_casefold_cache ();f2fs_destroy_compress_cache ();f2fs_destroy_compress_mempool ();
fs/f2fs/xattr.c +10 -20
@@ -23,11 +23,12 @@#include "xattr.h" #include "segment.h" +static struct kmem_cache *inline_xattr_slab;static void *xattr_alloc (struct f2fs_sb_info *sbi,int size,bool *is_inline) { -if (likely (size == sbi->inline_xattr_slab_size)) { +if (likely (size ==DEFAULT_XATTR_SLAB_SIZE )) { *is_inline = true; -return f2fs_kmem_cache_alloc (sbi->inline_xattr_slab, +return f2fs_kmem_cache_alloc (inline_xattr_slab,GFP_F2FS_ZERO , false, sbi); } *is_inline = false;
@@ -38,7 +39,7 @@ static void xattr_free(struct f2fs_sb_in bool is_inline) {if (is_inline) -kmem_cache_free (sbi->inline_xattr_slab, xattr_addr); +kmem_cache_free (inline_xattr_slab, xattr_addr);else kfree (xattr_addr); }
@@ -830,25 +831,14 @@ int f2fs_setxattr(struct inode *inode, ireturn err; } -int f2fs_init_xattr_caches (struct f2fs_sb_info *sbi) +int __init f2fs_init_xattr_cache (void ) { -dev_t dev = sbi->sb->s_bdev->bd_dev; -char slab_name[32 ]; - -sprintf (slab_name,"f2fs_xattr_entry-%u:%u" ,MAJOR (dev),MINOR (dev)); - - sbi->inline_xattr_slab_size =F2FS_OPTION (sbi).inline_xattr_size * -sizeof (__le32) +XATTR_PADDING_SIZE ; - - sbi->inline_xattr_slab =f2fs_kmem_cache_create (slab_name, - sbi->inline_xattr_slab_size); -if (!sbi->inline_xattr_slab) -return -ENOMEM ; - -return 0 ; + inline_xattr_slab =f2fs_kmem_cache_create ("f2fs_xattr_entry" , +DEFAULT_XATTR_SLAB_SIZE ); +return inline_xattr_slab ?0 : -ENOMEM ; } -void f2fs_destroy_xattr_caches (struct f2fs_sb_info *sbi) +void f2fs_destroy_xattr_cache (void ) { -kmem_cache_destroy (sbi->inline_xattr_slab); +kmem_cache_destroy (inline_xattr_slab); }
fs/f2fs/xattr.h +6 -4
@@ -89,6 +89,8 @@ struct f2fs_xattr_entry { F2FS_TOTAL_EXTRA_ATTR_SIZE / sizeof(__le32) - \ DEF_INLINE_RESERVED_SIZE - \ MIN_INLINE_DENTRY_SIZE / sizeof(__le32)) +#define DEFAULT_XATTR_SLAB_SIZE (DEFAULT_INLINE_XATTR_ADDRS * \ + sizeof(__le32) + XATTR_PADDING_SIZE)/* * On-disk structure of f2fs_xattr
@@ -132,8 +134,8 @@ extern int f2fs_setxattr(struct inode *,extern int f2fs_getxattr (struct inode *,int ,const char *,void *,size_t ,struct page *);extern ssize_t f2fs_listxattr (struct dentry *,char *,size_t ); -extern int f2fs_init_xattr_caches (struct f2fs_sb_info *); -extern void f2fs_destroy_xattr_caches (struct f2fs_sb_info *); +extern int __init f2fs_init_xattr_cache (void ); +extern void f2fs_destroy_xattr_cache (void );#else #define f2fs_xattr_handlers NULL
@@ -150,8 +152,8 @@ static inline int f2fs_getxattr(struct i {return -EOPNOTSUPP ; } -static inline int f2fs_init_xattr_caches (struct f2fs_sb_info *sbi) {return 0 ; } -static inline void f2fs_destroy_xattr_caches (struct f2fs_sb_info *sbi) { } +static inline int __init f2fs_init_xattr_cache (void ) {return 0 ; } +static inline void f2fs_destroy_xattr_cache (void ) { }#endif #ifdef CONFIG_F2FS_FS_SECURITY
Greg Kroah-Hartman
maintainerPATCH 690/737 f2fs: fix to detect recoverable inode during dryrun of find_fsync_dnodes()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chao Yu <[email protected]>
[ Upstream commit 68d05693f8c031257a0822464366e1c2a239a512 ]
mkfs.f2fs -f /dev/vdd
mount /dev/vdd /mnt/f2fs
touch /mnt/f2fs/foo
sync # avoid CP_UMOUNT_FLAG in last f2fs_checkpoint.ckpt_flags
touch /mnt/f2fs/barf2fs_io fsync /mnt/f2fs/barf2fs_io shutdown 2 /mnt/f2fs
umount /mnt/f2fs
blockdev --setro /dev/vdd
mount /dev/vdd /mnt/f2fs
mount: /mnt/f2fs: WARNING: source write-protected, mounted read-only.
For the case if we create and fsync a new inode before sudden power-cut, without norecovery or disable_roll_forward mount option, the following mount will succeed w/o recovering last fsynced inode.
The problem here is that we only check inode_list list after find_fsync_dnodes() in f2fs_recover_fsync_data() to find out whether there is recoverable data in the iamge, but there is a missed case, if last fsynced inode is not existing in last checkpoint, then, we will fail to get its inode due to nat of inode node is not existing in last checkpoint, so the inode won't be linked in inode_list.
Let's detect such case in dyrun mode to fix this issue.
After this change, mount will fail as expected below:
mount: /mnt/f2fs: cannot mount /dev/vdd read-only.
dmesg(1) may have more information after failed mount system call.
demsg:
F2FS-fs (vdd): Need to recover fsync data, but write access unavailable, please try mount w/ disable_roll_forward or norecovery
--- fs/f2fs/recovery.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-)
fs/f2fs/recovery.c +12 -8
@@ -404,7 +404,7 @@ static int sanity_check_node_chain(struc }static int find_fsync_dnodes (struct f2fs_sb_info *sbi,struct list_head *head, -bool check_only) +bool check_only,bool *new_inode) {struct curseg_info *curseg;struct page *page =NULL ;
@@ -451,16 +451,19 @@ static int find_fsync_dnodes(struct f2fs quota_inode = true; } -/* -* CP | dnode(F) | inode(DF) -* For this case, we should not give up now. -*/ entry =add_fsync_inode (sbi, head,ino_of_node (page), quota_inode);if (IS_ERR (entry)) { err =PTR_ERR (entry); -if (err == -ENOENT ) +/* +* CP | dnode(F) | inode(DF) +* For this case, we should not give up now. +*/ +if (err == -ENOENT ) { +if (check_only) + *new_inode = true; goto next; + }f2fs_put_page (page,1 );break ; }
@@ -863,6 +866,7 @@ int f2fs_recover_fsync_data(struct f2fs_unsigned long s_flags = sbi->sb->s_flags;bool need_writecp = false;bool fix_curseg_write_pointer = false; +bool new_inode = false;if (is_sbi_flag_set (sbi,SBI_IS_WRITABLE ))f2fs_info (sbi,"recover fsync data on readonly fs" );
@@ -875,8 +879,8 @@ int f2fs_recover_fsync_data(struct f2fs_f2fs_down_write (&sbi->cp_global_sem);/* step #1: find fsynced inode numbers */ - err =find_fsync_dnodes (sbi, &inode_list, check_only); -if (err ||list_empty (&inode_list)) + err =find_fsync_dnodes (sbi, &inode_list, check_only, &new_inode); +if (err <0 || (list_empty (&inode_list) && (!check_only || !new_inode))) goto skip;if (check_only) {
Greg Kroah-Hartman
maintainerPATCH 691/737 media: verisilicon: Store chroma and motion vectors offset
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Gaignard <[email protected]>
[ Upstream commit 545bf944f978b7468d3a6bd668d9ff6953bc542e ]
Store computed values of chroma and motion vectors offset because they depends on width and height values which change if the resolution change.
Stable-dep-of: 19c286b75507 ("media: verisilicon: Fix CPU stalls on G2 bus error")
--- drivers/media/platform/verisilicon/hantro.h | 2 ++ drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-)
drivers/media/platform/verisilicon/hantro.h +2 -0
@@ -328,6 +328,8 @@ struct hantro_vp9_decoded_buffer_info {/* Info needed when the decoded frame serves as a reference frame. */ unsigned short width;unsigned short height; +size_t chroma_offset; +size_t mv_offset; u32 bit_depth : 4; };
drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c +4 -2
@@ -158,9 +158,11 @@ static void config_output(struct hantro_ chroma_addr = luma_addr +chroma_offset (ctx, dec_params);hantro_write_addr (ctx->dev,G2_OUT_CHROMA_ADDR , chroma_addr); + dst->vp9.chroma_offset =chroma_offset (ctx, dec_params); mv_addr = luma_addr +mv_offset (ctx, dec_params);hantro_write_addr (ctx->dev,G2_OUT_MV_ADDR , mv_addr); + dst->vp9.mv_offset =mv_offset (ctx, dec_params); }struct hantro_vp9_ref_reg {
@@ -195,7 +197,7 @@ static void config_ref(struct hantro_ctx luma_addr =hantro_get_dec_buf_addr (ctx, &buf->base.vb.vb2_buf);hantro_write_addr (ctx->dev, ref_reg->y_base, luma_addr); - chroma_addr = luma_addr +chroma_offset (ctx, dec_params); + chroma_addr = luma_addr + buf->vp9.chroma_offset;hantro_write_addr (ctx->dev, ref_reg->c_base, chroma_addr); }
@@ -238,7 +240,7 @@ static void config_ref_registers(structconfig_ref (ctx, dst, &ref_regs[2 ], dec_params, dec_params->alt_frame_ts); mv_addr =hantro_get_dec_buf_addr (ctx, &mv_ref->base.vb.vb2_buf) + -mv_offset (ctx, dec_params); + mv_ref->vp9.mv_offset;hantro_write_addr (ctx->dev,G2_REF_MV_ADDR (0 ), mv_addr); hantro_reg_write(ctx->dev, &vp9_last_sign_bias,
Greg Kroah-Hartman
maintainerPATCH 692/737 media: verisilicon: g2: Use common helpers to compute chroma and mv offsets
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Gaignard <[email protected]>
[ Upstream commit 3eeaee737dcee3c32e256870dbc2687a2a6fe970 ]
HEVC and VP9 are running on the same hardware and share the same chroma and motion vectors offset constraint.
Create common helpers functions for these computation. Source and destination buffer height may not be the same because alignment constraint are different so use destination height to compute chroma offset because we target this buffer as hardware output.
To be able to use the helpers in both VP9 HEVC code remove dec_params and use context->bit_depth instead.
Stable-dep-of: 19c286b75507 ("media: verisilicon: Fix CPU stalls on G2 bus error")
--- drivers/media/platform/verisilicon/hantro_g2.c | 14 ++++++++ drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c | 18 +---------- drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c | 26 ++-------------- drivers/media/platform/verisilicon/hantro_hw.h | 3 + 4 files changed, 23 insertions(+), 38 deletions(-)
drivers/media/platform/verisilicon/hantro_g2.c +14 -0
@@ -8,6 +8,8 @@#include "hantro_hw.h" #include "hantro_g2_regs.h" +#define G2_ALIGN 16 +void hantro_g2_check_idle (struct hantro_dev *vpu) {int i;
@@ -42,3 +44,15 @@ irqreturn_t hantro_g2_irq(int irq, voidreturn IRQ_HANDLED ; } + +size_t hantro_g2_chroma_offset (struct hantro_ctx *ctx) +{ +return ctx->dst_fmt.width * ctx->dst_fmt.height * ctx->bit_depth /8 ; +} + +size_t hantro_g2_motion_vectors_offset (struct hantro_ctx *ctx) +{ +size_t cr_offset =hantro_g2_chroma_offset (ctx); + +return ALIGN ((cr_offset *3 ) /2 ,G2_ALIGN ); +}
drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c +2 -16
@@ -8,20 +8,6 @@#include "hantro_hw.h" #include "hantro_g2_regs.h" -#define G2_ALIGN 16 - -static size_t hantro_hevc_chroma_offset (struct hantro_ctx *ctx) -{ -return ctx->dst_fmt.width * ctx->dst_fmt.height * ctx->bit_depth /8 ; -} - -static size_t hantro_hevc_motion_vectors_offset (struct hantro_ctx *ctx) -{ -size_t cr_offset =hantro_hevc_chroma_offset (ctx); - -return ALIGN ((cr_offset *3 ) /2 ,G2_ALIGN ); -} -static void prepare_tile_info_buffer (struct hantro_ctx *ctx) {struct hantro_dev *vpu = ctx->dev;
@@ -395,8 +381,8 @@ static int set_ref(struct hantro_ctx *ctstruct hantro_dev *vpu = ctx->dev;struct vb2_v4l2_buffer *vb2_dst;struct hantro_decoded_buffer *dst; -size_t cr_offset =hantro_hevc_chroma_offset (ctx); -size_t mv_offset =hantro_hevc_motion_vectors_offset (ctx); +size_t cr_offset =hantro_g2_chroma_offset (ctx); +size_t mv_offset =hantro_g2_motion_vectors_offset (ctx);u32 max_ref_frames;u16 dpb_longterm_e;static const struct hantro_reg cur_poc[] = {
drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c +4 -22
@@ -16,8 +16,6 @@#include "hantro_vp9.h" #include "hantro_g2_regs.h" -#define G2_ALIGN 16 -enum hantro_ref_frames {INTRA_FRAME =0 ,LAST_FRAME =1 ,
@@ -90,22 +88,6 @@ static int start_prepare_run(struct hantreturn 0 ; } -static size_t chroma_offset (const struct hantro_ctx *ctx, -const struct v4l2_ctrl_vp9_frame *dec_params) -{ -int bytes_per_pixel = dec_params->bit_depth ==8 ?1 :2 ; - -return ctx->src_fmt.width * ctx->src_fmt.height * bytes_per_pixel; -} - -static size_t mv_offset (const struct hantro_ctx *ctx, -const struct v4l2_ctrl_vp9_frame *dec_params) -{ -size_t cr_offset =chroma_offset (ctx, dec_params); - -return ALIGN ((cr_offset *3 ) /2 ,G2_ALIGN ); -} -static struct hantro_decoded_buffer *get_ref_buf (struct hantro_ctx *ctx,struct vb2_v4l2_buffer *dst,u64 timestamp) {
@@ -156,13 +138,13 @@ static void config_output(struct hantro_ luma_addr =hantro_get_dec_buf_addr (ctx, &dst->base.vb.vb2_buf);hantro_write_addr (ctx->dev,G2_OUT_LUMA_ADDR , luma_addr); - chroma_addr = luma_addr +chroma_offset (ctx, dec_params); + chroma_addr = luma_addr +hantro_g2_chroma_offset (ctx);hantro_write_addr (ctx->dev,G2_OUT_CHROMA_ADDR , chroma_addr); - dst->vp9.chroma_offset =chroma_offset (ctx, dec_params); + dst->vp9.chroma_offset =hantro_g2_chroma_offset (ctx); - mv_addr = luma_addr +mv_offset (ctx, dec_params); + mv_addr = luma_addr +hantro_g2_motion_vectors_offset (ctx);hantro_write_addr (ctx->dev,G2_OUT_MV_ADDR , mv_addr); - dst->vp9.mv_offset =mv_offset (ctx, dec_params); + dst->vp9.mv_offset =hantro_g2_motion_vectors_offset (ctx); }struct hantro_vp9_ref_reg {
drivers/media/platform/verisilicon/hantro_hw.h +3 -0
@@ -519,6 +519,9 @@ hantro_av1_mv_size(unsigned int width, ureturn ALIGN (num_sbs *384 ,16 ) *2 +512 ; } +size_t hantro_g2_chroma_offset (struct hantro_ctx *ctx); +size_t hantro_g2_motion_vectors_offset (struct hantro_ctx *ctx); +int hantro_g1_mpeg2_dec_run (struct hantro_ctx *ctx);int rockchip_vpu2_mpeg2_dec_run (struct hantro_ctx *ctx); void hantro_mpeg2_dec_copy_qtable(u8 *qtable,