From: Greg Kroah-Hartman Date: Tue, 8 Jun 2021 12:32:17 +0000 (+0200) Subject: 5.12-stable patches X-Git-Tag: v4.4.272~53 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=cd7dbd9696772dd89e131a4162120e6e2ad7cea3;p=thirdparty%2Fkernel%2Fstable-queue.git 5.12-stable patches added patches: alsa-hda-fix-for-mute-key-led-for-hp-pavilion-15-ck0xx.patch alsa-hda-update-the-power_state-during-the-direct-complete.patch alsa-timer-fix-master-timer-notification.patch arm-dts-imx6dl-yapp4-fix-rgmii-connection-to-qca8334-switch.patch arm-dts-imx6q-dhcom-add-pu-vdd1p1-vdd2p5-regulators.patch ext4-fix-accessing-uninit-percpu-counter-variable-with-fast_commit.patch ext4-fix-bug-on-in-ext4_es_cache_extent-as-ext4_split_extent_at-failed.patch ext4-fix-fast-commit-alignment-issues.patch ext4-fix-memory-leak-in-ext4_fill_super.patch ext4-fix-memory-leak-in-ext4_mb_init_backend-on-error-path.patch gfs2-fix-scheduling-while-atomic-bug-in-glocks.patch hid-i2c-hid-skip-elan-power-on-command-after-reset.patch hid-magicmouse-fix-null-deref-on-disconnect.patch hid-multitouch-require-finger-field-to-mark-win8-reports-as-mt.patch net-caif-add-proper-error-handling.patch net-caif-added-cfserl_release-function.patch net-caif-fix-memory-leak-in-caif_device_notify.patch net-caif-fix-memory-leak-in-cfusbl_device_notify.patch net-kcm-fix-memory-leak-in-kcm_sendmsg.patch --- diff --git a/queue-5.12/alsa-hda-fix-for-mute-key-led-for-hp-pavilion-15-ck0xx.patch b/queue-5.12/alsa-hda-fix-for-mute-key-led-for-hp-pavilion-15-ck0xx.patch new file mode 100644 index 00000000000..5b6500fa146 --- /dev/null +++ b/queue-5.12/alsa-hda-fix-for-mute-key-led-for-hp-pavilion-15-ck0xx.patch @@ -0,0 +1,32 @@ +From 901be145a46eb79879367d853194346a549e623d Mon Sep 17 00:00:00 2001 +From: Carlos M +Date: Mon, 31 May 2021 22:20:26 +0200 +Subject: ALSA: hda: Fix for mute key LED for HP Pavilion 15-CK0xx + +From: Carlos M + +commit 901be145a46eb79879367d853194346a549e623d upstream. + +For the HP Pavilion 15-CK0xx, with audio subsystem ID 0x103c:0x841c, +adding a line in patch_realtek.c to apply the ALC269_FIXUP_HP_MUTE_LED_MIC3 +fix activates the mute key LED. + +Signed-off-by: Carlos M +Cc: +Link: https://lore.kernel.org/r/20210531202026.35427-1-carlos.marr.pz@gmail.com +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/pci/hda/patch_realtek.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -8289,6 +8289,7 @@ static const struct snd_pci_quirk alc269 + SND_PCI_QUIRK(0x103c, 0x82bf, "HP G3 mini", ALC221_FIXUP_HP_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x103c, 0x82c0, "HP G3 mini premium", ALC221_FIXUP_HP_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x103c, 0x83b9, "HP Spectre x360", ALC269_FIXUP_HP_MUTE_LED_MIC3), ++ SND_PCI_QUIRK(0x103c, 0x841c, "HP Pavilion 15-CK0xx", ALC269_FIXUP_HP_MUTE_LED_MIC3), + SND_PCI_QUIRK(0x103c, 0x8497, "HP Envy x360", ALC269_FIXUP_HP_MUTE_LED_MIC3), + SND_PCI_QUIRK(0x103c, 0x84da, "HP OMEN dc0019-ur", ALC295_FIXUP_HP_OMEN), + SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3), diff --git a/queue-5.12/alsa-hda-update-the-power_state-during-the-direct-complete.patch b/queue-5.12/alsa-hda-update-the-power_state-during-the-direct-complete.patch new file mode 100644 index 00000000000..05b6890a2b9 --- /dev/null +++ b/queue-5.12/alsa-hda-update-the-power_state-during-the-direct-complete.patch @@ -0,0 +1,55 @@ +From b8b90c17602689eeaa5b219d104bbc215d1225cc Mon Sep 17 00:00:00 2001 +From: Hui Wang +Date: Wed, 2 Jun 2021 22:54:24 +0800 +Subject: ALSA: hda: update the power_state during the direct-complete + +From: Hui Wang + +commit b8b90c17602689eeaa5b219d104bbc215d1225cc upstream. + +The patch_realtek.c needs to check if the power_state.event equals +PM_EVENT_SUSPEND, after using the direct-complete, the suspend() and +resume() will be skipped if the codec is already rt_suspended, in this +case, the patch_realtek.c will always get PM_EVENT_ON even the system +is really resumed from S3. + +We could set power_state to PMSG_SUSPEND in the prepare(), if other +PM functions are called before complete(), those functions will +override power_state; if no other PM functions are called before +complete(), we could know the suspend() and resume() are skipped since +only S3 pm functions could be skipped by direct-complete, in this case +set power_state to PMSG_RESUME in the complete(). This could guarantee +the first time of calling hda_codec_runtime_resume() after complete() +has the correct power_state. + +Fixes: 215a22ed31a1 ("ALSA: hda: Refactor codec PM to use direct-complete optimization") +Cc: +Signed-off-by: Hui Wang +Link: https://lore.kernel.org/r/20210602145424.3132-1-hui.wang@canonical.com +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/pci/hda/hda_codec.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/sound/pci/hda/hda_codec.c ++++ b/sound/pci/hda/hda_codec.c +@@ -2973,6 +2973,7 @@ static int hda_codec_runtime_resume(stru + #ifdef CONFIG_PM_SLEEP + static int hda_codec_pm_prepare(struct device *dev) + { ++ dev->power.power_state = PMSG_SUSPEND; + return pm_runtime_suspended(dev); + } + +@@ -2980,6 +2981,10 @@ static void hda_codec_pm_complete(struct + { + struct hda_codec *codec = dev_to_hda_codec(dev); + ++ /* If no other pm-functions are called between prepare() and complete() */ ++ if (dev->power.power_state.event == PM_EVENT_SUSPEND) ++ dev->power.power_state = PMSG_RESUME; ++ + if (pm_runtime_suspended(dev) && (codec->jackpoll_interval || + hda_codec_need_resume(codec) || codec->forced_resume)) + pm_request_resume(dev); diff --git a/queue-5.12/alsa-timer-fix-master-timer-notification.patch b/queue-5.12/alsa-timer-fix-master-timer-notification.patch new file mode 100644 index 00000000000..0b4deb23923 --- /dev/null +++ b/queue-5.12/alsa-timer-fix-master-timer-notification.patch @@ -0,0 +1,39 @@ +From 9c1fe96bded935369f8340c2ac2e9e189f697d5d Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Wed, 2 Jun 2021 13:38:23 +0200 +Subject: ALSA: timer: Fix master timer notification + +From: Takashi Iwai + +commit 9c1fe96bded935369f8340c2ac2e9e189f697d5d upstream. + +snd_timer_notify1() calls the notification to each slave for a master +event, but it passes a wrong event number. It should be +10 offset, +corresponding to SNDRV_TIMER_EVENT_MXXX, but it's incorrectly with ++100 offset. Casually this was spotted by UBSAN check via syzkaller. + +Reported-by: syzbot+d102fa5b35335a7e544e@syzkaller.appspotmail.com +Reviewed-by: Jaroslav Kysela +Cc: +Link: https://lore.kernel.org/r/000000000000e5560e05c3bd1d63@google.com +Link: https://lore.kernel.org/r/20210602113823.23777-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/core/timer.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/sound/core/timer.c ++++ b/sound/core/timer.c +@@ -520,9 +520,10 @@ static void snd_timer_notify1(struct snd + return; + if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) + return; ++ event += 10; /* convert to SNDRV_TIMER_EVENT_MXXX */ + list_for_each_entry(ts, &ti->slave_active_head, active_list) + if (ts->ccallback) +- ts->ccallback(ts, event + 100, &tstamp, resolution); ++ ts->ccallback(ts, event, &tstamp, resolution); + } + + /* start/continue a master timer */ diff --git a/queue-5.12/arm-dts-imx6dl-yapp4-fix-rgmii-connection-to-qca8334-switch.patch b/queue-5.12/arm-dts-imx6dl-yapp4-fix-rgmii-connection-to-qca8334-switch.patch new file mode 100644 index 00000000000..03bf4304a2b --- /dev/null +++ b/queue-5.12/arm-dts-imx6dl-yapp4-fix-rgmii-connection-to-qca8334-switch.patch @@ -0,0 +1,47 @@ +From 0e4a4a08cd78efcaddbc2e4c5ed86b5a5cb8a15e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Vok=C3=A1=C4=8D?= +Date: Tue, 13 Apr 2021 16:45:57 +0200 +Subject: ARM: dts: imx6dl-yapp4: Fix RGMII connection to QCA8334 switch +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Michal Vokáč + +commit 0e4a4a08cd78efcaddbc2e4c5ed86b5a5cb8a15e upstream. + +The FEC does not have a PHY so it should not have a phy-handle. It is +connected to the switch at RGMII level so we need a fixed-link sub-node +on both ends. + +This was not a problem until the qca8k.c driver was converted to PHYLINK +by commit b3591c2a3661 ("net: dsa: qca8k: Switch to PHYLINK instead of +PHYLIB"). That commit revealed the FEC configuration was not correct. + +Fixes: 87489ec3a77f ("ARM: dts: imx: Add Y Soft IOTA Draco, Hydra and Ursa boards") +Cc: stable@vger.kernel.org +Signed-off-by: Michal Vokáč +Reviewed-by: Andrew Lunn +Signed-off-by: Shawn Guo +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm/boot/dts/imx6dl-yapp4-common.dtsi | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/imx6dl-yapp4-common.dtsi ++++ b/arch/arm/boot/dts/imx6dl-yapp4-common.dtsi +@@ -105,9 +105,13 @@ + phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>; + phy-reset-duration = <20>; + phy-supply = <&sw2_reg>; +- phy-handle = <ðphy0>; + status = "okay"; + ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++ + mdio { + #address-cells = <1>; + #size-cells = <0>; diff --git a/queue-5.12/arm-dts-imx6q-dhcom-add-pu-vdd1p1-vdd2p5-regulators.patch b/queue-5.12/arm-dts-imx6q-dhcom-add-pu-vdd1p1-vdd2p5-regulators.patch new file mode 100644 index 00000000000..d978af2d218 --- /dev/null +++ b/queue-5.12/arm-dts-imx6q-dhcom-add-pu-vdd1p1-vdd2p5-regulators.patch @@ -0,0 +1,54 @@ +From 8967b27a6c1c19251989c7ab33c058d16e4a5f53 Mon Sep 17 00:00:00 2001 +From: Marek Vasut +Date: Mon, 26 Apr 2021 12:23:21 +0200 +Subject: ARM: dts: imx6q-dhcom: Add PU,VDD1P1,VDD2P5 regulators + +From: Marek Vasut + +commit 8967b27a6c1c19251989c7ab33c058d16e4a5f53 upstream. + +Per schematic, both PU and SOC regulator are supplied from LTC3676 SW1 +via VDDSOC_IN rail, add the PU input. Both VDD1P1, VDD2P5 are supplied +from LTC3676 SW2 via VDDHIGH_IN rail, add both inputs. + +While no instability or problems are currently observed, the regulators +should be fully described in DT and that description should fully match +the hardware, else this might lead to unforseen issues later. Fix this. + +Fixes: 52c7a088badd ("ARM: dts: imx6q: Add support for the DHCOM iMX6 SoM and PDK2") +Reviewed-by: Fabio Estevam +Signed-off-by: Marek Vasut +Cc: Christoph Niedermaier +Cc: Fabio Estevam +Cc: Ludwig Zenz +Cc: NXP Linux Team +Cc: Shawn Guo +Cc: stable@vger.kernel.org +Reviewed-by: Christoph Niedermaier +Signed-off-by: Shawn Guo +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm/boot/dts/imx6q-dhcom-som.dtsi | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/arch/arm/boot/dts/imx6q-dhcom-som.dtsi ++++ b/arch/arm/boot/dts/imx6q-dhcom-som.dtsi +@@ -406,6 +406,18 @@ + vin-supply = <&sw1_reg>; + }; + ++®_pu { ++ vin-supply = <&sw1_reg>; ++}; ++ ++®_vdd1p1 { ++ vin-supply = <&sw2_reg>; ++}; ++ ++®_vdd2p5 { ++ vin-supply = <&sw2_reg>; ++}; ++ + &uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; diff --git a/queue-5.12/ext4-fix-accessing-uninit-percpu-counter-variable-with-fast_commit.patch b/queue-5.12/ext4-fix-accessing-uninit-percpu-counter-variable-with-fast_commit.patch new file mode 100644 index 00000000000..2ff28a4baec --- /dev/null +++ b/queue-5.12/ext4-fix-accessing-uninit-percpu-counter-variable-with-fast_commit.patch @@ -0,0 +1,75 @@ +From b45f189a19b38e01676628db79cd3eeb1333516e Mon Sep 17 00:00:00 2001 +From: Ritesh Harjani +Date: Thu, 29 Apr 2021 16:13:44 +0530 +Subject: ext4: fix accessing uninit percpu counter variable with fast_commit + +From: Ritesh Harjani + +commit b45f189a19b38e01676628db79cd3eeb1333516e upstream. + +When running generic/527 with fast_commit configuration, the following +issue is seen on Power. With fast_commit, during ext4_fc_replay() +(which can be called from ext4_fill_super()), if inode eviction +happens then it can access an uninitialized percpu counter variable. + +This patch adds the check before accessing the counters in +ext4_free_inode() path. + +[ 321.165371] run fstests generic/527 at 2021-04-29 08:38:43 +[ 323.027786] EXT4-fs (dm-0): mounted filesystem with ordered data mode. Opts: block_validity. Quota mode: none. +[ 323.618772] BUG: Unable to handle kernel data access on read at 0x1fbd80000 +[ 323.619767] Faulting instruction address: 0xc000000000bae78c +cpu 0x1: Vector: 300 (Data Access) at [c000000010706ef0] + pc: c000000000bae78c: percpu_counter_add_batch+0x3c/0x100 + lr: c0000000006d0bb0: ext4_free_inode+0x780/0xb90 + pid = 5593, comm = mount + ext4_free_inode+0x780/0xb90 + ext4_evict_inode+0xa8c/0xc60 + evict+0xfc/0x1e0 + ext4_fc_replay+0xc50/0x20f0 + do_one_pass+0xfe0/0x1350 + jbd2_journal_recover+0x184/0x2e0 + jbd2_journal_load+0x1c0/0x4a0 + ext4_fill_super+0x2458/0x4200 + mount_bdev+0x1dc/0x290 + ext4_mount+0x28/0x40 + legacy_get_tree+0x4c/0xa0 + vfs_get_tree+0x4c/0x120 + path_mount+0xcf8/0xd70 + do_mount+0x80/0xd0 + sys_mount+0x3fc/0x490 + system_call_exception+0x384/0x3d0 + system_call_common+0xec/0x278 + +Cc: stable@kernel.org +Fixes: 8016e29f4362 ("ext4: fast commit recovery path") +Signed-off-by: Ritesh Harjani +Reviewed-by: Harshad Shirwadkar +Link: https://lore.kernel.org/r/6cceb9a75c54bef8fa9696c1b08c8df5ff6169e2.1619692410.git.riteshh@linux.ibm.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/ialloc.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/fs/ext4/ialloc.c ++++ b/fs/ext4/ialloc.c +@@ -322,14 +322,16 @@ void ext4_free_inode(handle_t *handle, s + if (is_directory) { + count = ext4_used_dirs_count(sb, gdp) - 1; + ext4_used_dirs_set(sb, gdp, count); +- percpu_counter_dec(&sbi->s_dirs_counter); ++ if (percpu_counter_initialized(&sbi->s_dirs_counter)) ++ percpu_counter_dec(&sbi->s_dirs_counter); + } + ext4_inode_bitmap_csum_set(sb, block_group, gdp, bitmap_bh, + EXT4_INODES_PER_GROUP(sb) / 8); + ext4_group_desc_csum_set(sb, block_group, gdp); + ext4_unlock_group(sb, block_group); + +- percpu_counter_inc(&sbi->s_freeinodes_counter); ++ if (percpu_counter_initialized(&sbi->s_freeinodes_counter)) ++ percpu_counter_inc(&sbi->s_freeinodes_counter); + if (sbi->s_log_groups_per_flex) { + struct flex_groups *fg; + diff --git a/queue-5.12/ext4-fix-bug-on-in-ext4_es_cache_extent-as-ext4_split_extent_at-failed.patch b/queue-5.12/ext4-fix-bug-on-in-ext4_es_cache_extent-as-ext4_split_extent_at-failed.patch new file mode 100644 index 00000000000..6911a2fe590 --- /dev/null +++ b/queue-5.12/ext4-fix-bug-on-in-ext4_es_cache_extent-as-ext4_split_extent_at-failed.patch @@ -0,0 +1,114 @@ +From 082cd4ec240b8734a82a89ffb890216ac98fec68 Mon Sep 17 00:00:00 2001 +From: Ye Bin +Date: Thu, 6 May 2021 22:10:42 +0800 +Subject: ext4: fix bug on in ext4_es_cache_extent as ext4_split_extent_at failed + +From: Ye Bin + +commit 082cd4ec240b8734a82a89ffb890216ac98fec68 upstream. + +We got follow bug_on when run fsstress with injecting IO fault: +[130747.323114] kernel BUG at fs/ext4/extents_status.c:762! +[130747.323117] Internal error: Oops - BUG: 0 [#1] SMP +...... +[130747.334329] Call trace: +[130747.334553] ext4_es_cache_extent+0x150/0x168 [ext4] +[130747.334975] ext4_cache_extents+0x64/0xe8 [ext4] +[130747.335368] ext4_find_extent+0x300/0x330 [ext4] +[130747.335759] ext4_ext_map_blocks+0x74/0x1178 [ext4] +[130747.336179] ext4_map_blocks+0x2f4/0x5f0 [ext4] +[130747.336567] ext4_mpage_readpages+0x4a8/0x7a8 [ext4] +[130747.336995] ext4_readpage+0x54/0x100 [ext4] +[130747.337359] generic_file_buffered_read+0x410/0xae8 +[130747.337767] generic_file_read_iter+0x114/0x190 +[130747.338152] ext4_file_read_iter+0x5c/0x140 [ext4] +[130747.338556] __vfs_read+0x11c/0x188 +[130747.338851] vfs_read+0x94/0x150 +[130747.339110] ksys_read+0x74/0xf0 + +This patch's modification is according to Jan Kara's suggestion in: +https://patchwork.ozlabs.org/project/linux-ext4/patch/20210428085158.3728201-1-yebin10@huawei.com/ +"I see. Now I understand your patch. Honestly, seeing how fragile is trying +to fix extent tree after split has failed in the middle, I would probably +go even further and make sure we fix the tree properly in case of ENOSPC +and EDQUOT (those are easily user triggerable). Anything else indicates a +HW problem or fs corruption so I'd rather leave the extent tree as is and +don't try to fix it (which also means we will not create overlapping +extents)." + +Cc: stable@kernel.org +Signed-off-by: Ye Bin +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20210506141042.3298679-1-yebin10@huawei.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/extents.c | 43 +++++++++++++++++++++++-------------------- + 1 file changed, 23 insertions(+), 20 deletions(-) + +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -3206,7 +3206,10 @@ static int ext4_split_extent_at(handle_t + ext4_ext_mark_unwritten(ex2); + + err = ext4_ext_insert_extent(handle, inode, ppath, &newex, flags); +- if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) { ++ if (err != -ENOSPC && err != -EDQUOT) ++ goto out; ++ ++ if (EXT4_EXT_MAY_ZEROOUT & split_flag) { + if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) { + if (split_flag & EXT4_EXT_DATA_VALID1) { + err = ext4_ext_zeroout(inode, ex2); +@@ -3232,25 +3235,22 @@ static int ext4_split_extent_at(handle_t + ext4_ext_pblock(&orig_ex)); + } + +- if (err) +- goto fix_extent_len; +- /* update the extent length and mark as initialized */ +- ex->ee_len = cpu_to_le16(ee_len); +- ext4_ext_try_to_merge(handle, inode, path, ex); +- err = ext4_ext_dirty(handle, inode, path + path->p_depth); +- if (err) +- goto fix_extent_len; +- +- /* update extent status tree */ +- err = ext4_zeroout_es(inode, &zero_ex); +- +- goto out; +- } else if (err) +- goto fix_extent_len; +- +-out: +- ext4_ext_show_leaf(inode, path); +- return err; ++ if (!err) { ++ /* update the extent length and mark as initialized */ ++ ex->ee_len = cpu_to_le16(ee_len); ++ ext4_ext_try_to_merge(handle, inode, path, ex); ++ err = ext4_ext_dirty(handle, inode, path + path->p_depth); ++ if (!err) ++ /* update extent status tree */ ++ err = ext4_zeroout_es(inode, &zero_ex); ++ /* If we failed at this point, we don't know in which ++ * state the extent tree exactly is so don't try to fix ++ * length of the original extent as it may do even more ++ * damage. ++ */ ++ goto out; ++ } ++ } + + fix_extent_len: + ex->ee_len = orig_ex.ee_len; +@@ -3260,6 +3260,9 @@ fix_extent_len: + */ + ext4_ext_dirty(handle, inode, path + path->p_depth); + return err; ++out: ++ ext4_ext_show_leaf(inode, path); ++ return err; + } + + /* diff --git a/queue-5.12/ext4-fix-fast-commit-alignment-issues.patch b/queue-5.12/ext4-fix-fast-commit-alignment-issues.patch new file mode 100644 index 00000000000..0555d5c3076 --- /dev/null +++ b/queue-5.12/ext4-fix-fast-commit-alignment-issues.patch @@ -0,0 +1,439 @@ +From a7ba36bc94f20b6c77f16364b9a23f582ea8faac Mon Sep 17 00:00:00 2001 +From: Harshad Shirwadkar +Date: Wed, 19 May 2021 14:59:20 -0700 +Subject: ext4: fix fast commit alignment issues + +From: Harshad Shirwadkar + +commit a7ba36bc94f20b6c77f16364b9a23f582ea8faac upstream. + +Fast commit recovery data on disk may not be aligned. So, when the +recovery code reads it, this patch makes sure that fast commit info +found on-disk is first memcpy-ed into an aligned variable before +accessing it. As a consequence of it, we also remove some macros that +could resulted in unaligned accesses. + +Cc: stable@kernel.org +Fixes: 8016e29f4362 ("ext4: fast commit recovery path") +Signed-off-by: Harshad Shirwadkar +Link: https://lore.kernel.org/r/20210519215920.2037527-1-harshads@google.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/fast_commit.c | 170 ++++++++++++++++++++++++++------------------------ + fs/ext4/fast_commit.h | 19 ----- + 2 files changed, 90 insertions(+), 99 deletions(-) + +--- a/fs/ext4/fast_commit.c ++++ b/fs/ext4/fast_commit.c +@@ -1288,28 +1288,29 @@ struct dentry_info_args { + }; + + static inline void tl_to_darg(struct dentry_info_args *darg, +- struct ext4_fc_tl *tl) ++ struct ext4_fc_tl *tl, u8 *val) + { +- struct ext4_fc_dentry_info *fcd; ++ struct ext4_fc_dentry_info fcd; + +- fcd = (struct ext4_fc_dentry_info *)ext4_fc_tag_val(tl); ++ memcpy(&fcd, val, sizeof(fcd)); + +- darg->parent_ino = le32_to_cpu(fcd->fc_parent_ino); +- darg->ino = le32_to_cpu(fcd->fc_ino); +- darg->dname = fcd->fc_dname; +- darg->dname_len = ext4_fc_tag_len(tl) - +- sizeof(struct ext4_fc_dentry_info); ++ darg->parent_ino = le32_to_cpu(fcd.fc_parent_ino); ++ darg->ino = le32_to_cpu(fcd.fc_ino); ++ darg->dname = val + offsetof(struct ext4_fc_dentry_info, fc_dname); ++ darg->dname_len = le16_to_cpu(tl->fc_len) - ++ sizeof(struct ext4_fc_dentry_info); + } + + /* Unlink replay function */ +-static int ext4_fc_replay_unlink(struct super_block *sb, struct ext4_fc_tl *tl) ++static int ext4_fc_replay_unlink(struct super_block *sb, struct ext4_fc_tl *tl, ++ u8 *val) + { + struct inode *inode, *old_parent; + struct qstr entry; + struct dentry_info_args darg; + int ret = 0; + +- tl_to_darg(&darg, tl); ++ tl_to_darg(&darg, tl, val); + + trace_ext4_fc_replay(sb, EXT4_FC_TAG_UNLINK, darg.ino, + darg.parent_ino, darg.dname_len); +@@ -1399,13 +1400,14 @@ out: + } + + /* Link replay function */ +-static int ext4_fc_replay_link(struct super_block *sb, struct ext4_fc_tl *tl) ++static int ext4_fc_replay_link(struct super_block *sb, struct ext4_fc_tl *tl, ++ u8 *val) + { + struct inode *inode; + struct dentry_info_args darg; + int ret = 0; + +- tl_to_darg(&darg, tl); ++ tl_to_darg(&darg, tl, val); + trace_ext4_fc_replay(sb, EXT4_FC_TAG_LINK, darg.ino, + darg.parent_ino, darg.dname_len); + +@@ -1450,9 +1452,10 @@ static int ext4_fc_record_modified_inode + /* + * Inode replay function + */ +-static int ext4_fc_replay_inode(struct super_block *sb, struct ext4_fc_tl *tl) ++static int ext4_fc_replay_inode(struct super_block *sb, struct ext4_fc_tl *tl, ++ u8 *val) + { +- struct ext4_fc_inode *fc_inode; ++ struct ext4_fc_inode fc_inode; + struct ext4_inode *raw_inode; + struct ext4_inode *raw_fc_inode; + struct inode *inode = NULL; +@@ -1460,9 +1463,9 @@ static int ext4_fc_replay_inode(struct s + int inode_len, ino, ret, tag = le16_to_cpu(tl->fc_tag); + struct ext4_extent_header *eh; + +- fc_inode = (struct ext4_fc_inode *)ext4_fc_tag_val(tl); ++ memcpy(&fc_inode, val, sizeof(fc_inode)); + +- ino = le32_to_cpu(fc_inode->fc_ino); ++ ino = le32_to_cpu(fc_inode.fc_ino); + trace_ext4_fc_replay(sb, tag, ino, 0, 0); + + inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL); +@@ -1474,12 +1477,13 @@ static int ext4_fc_replay_inode(struct s + + ext4_fc_record_modified_inode(sb, ino); + +- raw_fc_inode = (struct ext4_inode *)fc_inode->fc_raw_inode; ++ raw_fc_inode = (struct ext4_inode *) ++ (val + offsetof(struct ext4_fc_inode, fc_raw_inode)); + ret = ext4_get_fc_inode_loc(sb, ino, &iloc); + if (ret) + goto out; + +- inode_len = ext4_fc_tag_len(tl) - sizeof(struct ext4_fc_inode); ++ inode_len = le16_to_cpu(tl->fc_len) - sizeof(struct ext4_fc_inode); + raw_inode = ext4_raw_inode(&iloc); + + memcpy(raw_inode, raw_fc_inode, offsetof(struct ext4_inode, i_block)); +@@ -1547,14 +1551,15 @@ out: + * inode for which we are trying to create a dentry here, should already have + * been replayed before we start here. + */ +-static int ext4_fc_replay_create(struct super_block *sb, struct ext4_fc_tl *tl) ++static int ext4_fc_replay_create(struct super_block *sb, struct ext4_fc_tl *tl, ++ u8 *val) + { + int ret = 0; + struct inode *inode = NULL; + struct inode *dir = NULL; + struct dentry_info_args darg; + +- tl_to_darg(&darg, tl); ++ tl_to_darg(&darg, tl, val); + + trace_ext4_fc_replay(sb, EXT4_FC_TAG_CREAT, darg.ino, + darg.parent_ino, darg.dname_len); +@@ -1633,9 +1638,9 @@ static int ext4_fc_record_regions(struct + + /* Replay add range tag */ + static int ext4_fc_replay_add_range(struct super_block *sb, +- struct ext4_fc_tl *tl) ++ struct ext4_fc_tl *tl, u8 *val) + { +- struct ext4_fc_add_range *fc_add_ex; ++ struct ext4_fc_add_range fc_add_ex; + struct ext4_extent newex, *ex; + struct inode *inode; + ext4_lblk_t start, cur; +@@ -1645,15 +1650,14 @@ static int ext4_fc_replay_add_range(stru + struct ext4_ext_path *path = NULL; + int ret; + +- fc_add_ex = (struct ext4_fc_add_range *)ext4_fc_tag_val(tl); +- ex = (struct ext4_extent *)&fc_add_ex->fc_ex; ++ memcpy(&fc_add_ex, val, sizeof(fc_add_ex)); ++ ex = (struct ext4_extent *)&fc_add_ex.fc_ex; + + trace_ext4_fc_replay(sb, EXT4_FC_TAG_ADD_RANGE, +- le32_to_cpu(fc_add_ex->fc_ino), le32_to_cpu(ex->ee_block), ++ le32_to_cpu(fc_add_ex.fc_ino), le32_to_cpu(ex->ee_block), + ext4_ext_get_actual_len(ex)); + +- inode = ext4_iget(sb, le32_to_cpu(fc_add_ex->fc_ino), +- EXT4_IGET_NORMAL); ++ inode = ext4_iget(sb, le32_to_cpu(fc_add_ex.fc_ino), EXT4_IGET_NORMAL); + if (IS_ERR(inode)) { + jbd_debug(1, "Inode not found."); + return 0; +@@ -1762,32 +1766,33 @@ next: + + /* Replay DEL_RANGE tag */ + static int +-ext4_fc_replay_del_range(struct super_block *sb, struct ext4_fc_tl *tl) ++ext4_fc_replay_del_range(struct super_block *sb, struct ext4_fc_tl *tl, ++ u8 *val) + { + struct inode *inode; +- struct ext4_fc_del_range *lrange; ++ struct ext4_fc_del_range lrange; + struct ext4_map_blocks map; + ext4_lblk_t cur, remaining; + int ret; + +- lrange = (struct ext4_fc_del_range *)ext4_fc_tag_val(tl); +- cur = le32_to_cpu(lrange->fc_lblk); +- remaining = le32_to_cpu(lrange->fc_len); ++ memcpy(&lrange, val, sizeof(lrange)); ++ cur = le32_to_cpu(lrange.fc_lblk); ++ remaining = le32_to_cpu(lrange.fc_len); + + trace_ext4_fc_replay(sb, EXT4_FC_TAG_DEL_RANGE, +- le32_to_cpu(lrange->fc_ino), cur, remaining); ++ le32_to_cpu(lrange.fc_ino), cur, remaining); + +- inode = ext4_iget(sb, le32_to_cpu(lrange->fc_ino), EXT4_IGET_NORMAL); ++ inode = ext4_iget(sb, le32_to_cpu(lrange.fc_ino), EXT4_IGET_NORMAL); + if (IS_ERR(inode)) { +- jbd_debug(1, "Inode %d not found", le32_to_cpu(lrange->fc_ino)); ++ jbd_debug(1, "Inode %d not found", le32_to_cpu(lrange.fc_ino)); + return 0; + } + + ret = ext4_fc_record_modified_inode(sb, inode->i_ino); + + jbd_debug(1, "DEL_RANGE, inode %ld, lblk %d, len %d\n", +- inode->i_ino, le32_to_cpu(lrange->fc_lblk), +- le32_to_cpu(lrange->fc_len)); ++ inode->i_ino, le32_to_cpu(lrange.fc_lblk), ++ le32_to_cpu(lrange.fc_len)); + while (remaining > 0) { + map.m_lblk = cur; + map.m_len = remaining; +@@ -1808,8 +1813,8 @@ ext4_fc_replay_del_range(struct super_bl + } + + ret = ext4_punch_hole(inode, +- le32_to_cpu(lrange->fc_lblk) << sb->s_blocksize_bits, +- le32_to_cpu(lrange->fc_len) << sb->s_blocksize_bits); ++ le32_to_cpu(lrange.fc_lblk) << sb->s_blocksize_bits, ++ le32_to_cpu(lrange.fc_len) << sb->s_blocksize_bits); + if (ret) + jbd_debug(1, "ext4_punch_hole returned %d", ret); + ext4_ext_replay_shrink_inode(inode, +@@ -1925,11 +1930,11 @@ static int ext4_fc_replay_scan(journal_t + struct ext4_sb_info *sbi = EXT4_SB(sb); + struct ext4_fc_replay_state *state; + int ret = JBD2_FC_REPLAY_CONTINUE; +- struct ext4_fc_add_range *ext; +- struct ext4_fc_tl *tl; +- struct ext4_fc_tail *tail; +- __u8 *start, *end; +- struct ext4_fc_head *head; ++ struct ext4_fc_add_range ext; ++ struct ext4_fc_tl tl; ++ struct ext4_fc_tail tail; ++ __u8 *start, *end, *cur, *val; ++ struct ext4_fc_head head; + struct ext4_extent *ex; + + state = &sbi->s_fc_replay_state; +@@ -1956,15 +1961,17 @@ static int ext4_fc_replay_scan(journal_t + } + + state->fc_replay_expected_off++; +- fc_for_each_tl(start, end, tl) { ++ for (cur = start; cur < end; cur = cur + sizeof(tl) + le16_to_cpu(tl.fc_len)) { ++ memcpy(&tl, cur, sizeof(tl)); ++ val = cur + sizeof(tl); + jbd_debug(3, "Scan phase, tag:%s, blk %lld\n", +- tag2str(le16_to_cpu(tl->fc_tag)), bh->b_blocknr); +- switch (le16_to_cpu(tl->fc_tag)) { ++ tag2str(le16_to_cpu(tl.fc_tag)), bh->b_blocknr); ++ switch (le16_to_cpu(tl.fc_tag)) { + case EXT4_FC_TAG_ADD_RANGE: +- ext = (struct ext4_fc_add_range *)ext4_fc_tag_val(tl); +- ex = (struct ext4_extent *)&ext->fc_ex; ++ memcpy(&ext, val, sizeof(ext)); ++ ex = (struct ext4_extent *)&ext.fc_ex; + ret = ext4_fc_record_regions(sb, +- le32_to_cpu(ext->fc_ino), ++ le32_to_cpu(ext.fc_ino), + le32_to_cpu(ex->ee_block), ext4_ext_pblock(ex), + ext4_ext_get_actual_len(ex)); + if (ret < 0) +@@ -1978,18 +1985,18 @@ static int ext4_fc_replay_scan(journal_t + case EXT4_FC_TAG_INODE: + case EXT4_FC_TAG_PAD: + state->fc_cur_tag++; +- state->fc_crc = ext4_chksum(sbi, state->fc_crc, tl, +- sizeof(*tl) + ext4_fc_tag_len(tl)); ++ state->fc_crc = ext4_chksum(sbi, state->fc_crc, cur, ++ sizeof(tl) + le16_to_cpu(tl.fc_len)); + break; + case EXT4_FC_TAG_TAIL: + state->fc_cur_tag++; +- tail = (struct ext4_fc_tail *)ext4_fc_tag_val(tl); +- state->fc_crc = ext4_chksum(sbi, state->fc_crc, tl, +- sizeof(*tl) + ++ memcpy(&tail, val, sizeof(tail)); ++ state->fc_crc = ext4_chksum(sbi, state->fc_crc, cur, ++ sizeof(tl) + + offsetof(struct ext4_fc_tail, + fc_crc)); +- if (le32_to_cpu(tail->fc_tid) == expected_tid && +- le32_to_cpu(tail->fc_crc) == state->fc_crc) { ++ if (le32_to_cpu(tail.fc_tid) == expected_tid && ++ le32_to_cpu(tail.fc_crc) == state->fc_crc) { + state->fc_replay_num_tags = state->fc_cur_tag; + state->fc_regions_valid = + state->fc_regions_used; +@@ -2000,19 +2007,19 @@ static int ext4_fc_replay_scan(journal_t + state->fc_crc = 0; + break; + case EXT4_FC_TAG_HEAD: +- head = (struct ext4_fc_head *)ext4_fc_tag_val(tl); +- if (le32_to_cpu(head->fc_features) & ++ memcpy(&head, val, sizeof(head)); ++ if (le32_to_cpu(head.fc_features) & + ~EXT4_FC_SUPPORTED_FEATURES) { + ret = -EOPNOTSUPP; + break; + } +- if (le32_to_cpu(head->fc_tid) != expected_tid) { ++ if (le32_to_cpu(head.fc_tid) != expected_tid) { + ret = JBD2_FC_REPLAY_STOP; + break; + } + state->fc_cur_tag++; +- state->fc_crc = ext4_chksum(sbi, state->fc_crc, tl, +- sizeof(*tl) + ext4_fc_tag_len(tl)); ++ state->fc_crc = ext4_chksum(sbi, state->fc_crc, cur, ++ sizeof(tl) + le16_to_cpu(tl.fc_len)); + break; + default: + ret = state->fc_replay_num_tags ? +@@ -2036,11 +2043,11 @@ static int ext4_fc_replay(journal_t *jou + { + struct super_block *sb = journal->j_private; + struct ext4_sb_info *sbi = EXT4_SB(sb); +- struct ext4_fc_tl *tl; +- __u8 *start, *end; ++ struct ext4_fc_tl tl; ++ __u8 *start, *end, *cur, *val; + int ret = JBD2_FC_REPLAY_CONTINUE; + struct ext4_fc_replay_state *state = &sbi->s_fc_replay_state; +- struct ext4_fc_tail *tail; ++ struct ext4_fc_tail tail; + + if (pass == PASS_SCAN) { + state->fc_current_pass = PASS_SCAN; +@@ -2067,49 +2074,52 @@ static int ext4_fc_replay(journal_t *jou + start = (u8 *)bh->b_data; + end = (__u8 *)bh->b_data + journal->j_blocksize - 1; + +- fc_for_each_tl(start, end, tl) { ++ for (cur = start; cur < end; cur = cur + sizeof(tl) + le16_to_cpu(tl.fc_len)) { ++ memcpy(&tl, cur, sizeof(tl)); ++ val = cur + sizeof(tl); ++ + if (state->fc_replay_num_tags == 0) { + ret = JBD2_FC_REPLAY_STOP; + ext4_fc_set_bitmaps_and_counters(sb); + break; + } + jbd_debug(3, "Replay phase, tag:%s\n", +- tag2str(le16_to_cpu(tl->fc_tag))); ++ tag2str(le16_to_cpu(tl.fc_tag))); + state->fc_replay_num_tags--; +- switch (le16_to_cpu(tl->fc_tag)) { ++ switch (le16_to_cpu(tl.fc_tag)) { + case EXT4_FC_TAG_LINK: +- ret = ext4_fc_replay_link(sb, tl); ++ ret = ext4_fc_replay_link(sb, &tl, val); + break; + case EXT4_FC_TAG_UNLINK: +- ret = ext4_fc_replay_unlink(sb, tl); ++ ret = ext4_fc_replay_unlink(sb, &tl, val); + break; + case EXT4_FC_TAG_ADD_RANGE: +- ret = ext4_fc_replay_add_range(sb, tl); ++ ret = ext4_fc_replay_add_range(sb, &tl, val); + break; + case EXT4_FC_TAG_CREAT: +- ret = ext4_fc_replay_create(sb, tl); ++ ret = ext4_fc_replay_create(sb, &tl, val); + break; + case EXT4_FC_TAG_DEL_RANGE: +- ret = ext4_fc_replay_del_range(sb, tl); ++ ret = ext4_fc_replay_del_range(sb, &tl, val); + break; + case EXT4_FC_TAG_INODE: +- ret = ext4_fc_replay_inode(sb, tl); ++ ret = ext4_fc_replay_inode(sb, &tl, val); + break; + case EXT4_FC_TAG_PAD: + trace_ext4_fc_replay(sb, EXT4_FC_TAG_PAD, 0, +- ext4_fc_tag_len(tl), 0); ++ le16_to_cpu(tl.fc_len), 0); + break; + case EXT4_FC_TAG_TAIL: + trace_ext4_fc_replay(sb, EXT4_FC_TAG_TAIL, 0, +- ext4_fc_tag_len(tl), 0); +- tail = (struct ext4_fc_tail *)ext4_fc_tag_val(tl); +- WARN_ON(le32_to_cpu(tail->fc_tid) != expected_tid); ++ le16_to_cpu(tl.fc_len), 0); ++ memcpy(&tail, val, sizeof(tail)); ++ WARN_ON(le32_to_cpu(tail.fc_tid) != expected_tid); + break; + case EXT4_FC_TAG_HEAD: + break; + default: +- trace_ext4_fc_replay(sb, le16_to_cpu(tl->fc_tag), 0, +- ext4_fc_tag_len(tl), 0); ++ trace_ext4_fc_replay(sb, le16_to_cpu(tl.fc_tag), 0, ++ le16_to_cpu(tl.fc_len), 0); + ret = -ECANCELED; + break; + } +--- a/fs/ext4/fast_commit.h ++++ b/fs/ext4/fast_commit.h +@@ -153,13 +153,6 @@ struct ext4_fc_replay_state { + #define region_last(__region) (((__region)->lblk) + ((__region)->len) - 1) + #endif + +-#define fc_for_each_tl(__start, __end, __tl) \ +- for (tl = (struct ext4_fc_tl *)(__start); \ +- (__u8 *)tl < (__u8 *)(__end); \ +- tl = (struct ext4_fc_tl *)((__u8 *)tl + \ +- sizeof(struct ext4_fc_tl) + \ +- + le16_to_cpu(tl->fc_len))) +- + static inline const char *tag2str(__u16 tag) + { + switch (tag) { +@@ -186,16 +179,4 @@ static inline const char *tag2str(__u16 + } + } + +-/* Get length of a particular tlv */ +-static inline int ext4_fc_tag_len(struct ext4_fc_tl *tl) +-{ +- return le16_to_cpu(tl->fc_len); +-} +- +-/* Get a pointer to "value" of a tlv */ +-static inline __u8 *ext4_fc_tag_val(struct ext4_fc_tl *tl) +-{ +- return (__u8 *)tl + sizeof(*tl); +-} +- + #endif /* __FAST_COMMIT_H__ */ diff --git a/queue-5.12/ext4-fix-memory-leak-in-ext4_fill_super.patch b/queue-5.12/ext4-fix-memory-leak-in-ext4_fill_super.patch new file mode 100644 index 00000000000..465661bc9d4 --- /dev/null +++ b/queue-5.12/ext4-fix-memory-leak-in-ext4_fill_super.patch @@ -0,0 +1,74 @@ +From afd09b617db3786b6ef3dc43e28fe728cfea84df Mon Sep 17 00:00:00 2001 +From: Alexey Makhalov +Date: Fri, 21 May 2021 07:55:33 +0000 +Subject: ext4: fix memory leak in ext4_fill_super + +From: Alexey Makhalov + +commit afd09b617db3786b6ef3dc43e28fe728cfea84df upstream. + +Buffer head references must be released before calling kill_bdev(); +otherwise the buffer head (and its page referenced by b_data) will not +be freed by kill_bdev, and subsequently that bh will be leaked. + +If blocksizes differ, sb_set_blocksize() will kill current buffers and +page cache by using kill_bdev(). And then super block will be reread +again but using correct blocksize this time. sb_set_blocksize() didn't +fully free superblock page and buffer head, and being busy, they were +not freed and instead leaked. + +This can easily be reproduced by calling an infinite loop of: + + systemctl start .mount, and + systemctl stop .mount + +... since systemd creates a cgroup for each slice which it mounts, and +the bh leak get amplified by a dying memory cgroup that also never +gets freed, and memory consumption is much more easily noticed. + +Fixes: ce40733ce93d ("ext4: Check for return value from sb_set_blocksize") +Fixes: ac27a0ec112a ("ext4: initial copy of files from ext3") +Link: https://lore.kernel.org/r/20210521075533.95732-1-amakhalov@vmware.com +Signed-off-by: Alexey Makhalov +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/super.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -4449,14 +4449,20 @@ static int ext4_fill_super(struct super_ + } + + if (sb->s_blocksize != blocksize) { ++ /* ++ * bh must be released before kill_bdev(), otherwise ++ * it won't be freed and its page also. kill_bdev() ++ * is called by sb_set_blocksize(). ++ */ ++ brelse(bh); + /* Validate the filesystem blocksize */ + if (!sb_set_blocksize(sb, blocksize)) { + ext4_msg(sb, KERN_ERR, "bad block size %d", + blocksize); ++ bh = NULL; + goto failed_mount; + } + +- brelse(bh); + logical_sb_block = sb_block * EXT4_MIN_BLOCK_SIZE; + offset = do_div(logical_sb_block, blocksize); + bh = ext4_sb_bread_unmovable(sb, logical_sb_block); +@@ -5176,8 +5182,9 @@ failed_mount: + kfree(get_qf_name(sb, sbi, i)); + #endif + fscrypt_free_dummy_policy(&sbi->s_dummy_enc_policy); +- ext4_blkdev_remove(sbi); ++ /* ext4_blkdev_remove() calls kill_bdev(), release bh before it. */ + brelse(bh); ++ ext4_blkdev_remove(sbi); + out_fail: + sb->s_fs_info = NULL; + kfree(sbi->s_blockgroup_lock); diff --git a/queue-5.12/ext4-fix-memory-leak-in-ext4_mb_init_backend-on-error-path.patch b/queue-5.12/ext4-fix-memory-leak-in-ext4_mb_init_backend-on-error-path.patch new file mode 100644 index 00000000000..1aa6bfc507a --- /dev/null +++ b/queue-5.12/ext4-fix-memory-leak-in-ext4_mb_init_backend-on-error-path.patch @@ -0,0 +1,33 @@ +From a8867f4e3809050571c98de7a2d465aff5e4daf5 Mon Sep 17 00:00:00 2001 +From: Phillip Potter +Date: Mon, 12 Apr 2021 08:38:37 +0100 +Subject: ext4: fix memory leak in ext4_mb_init_backend on error path. + +From: Phillip Potter + +commit a8867f4e3809050571c98de7a2d465aff5e4daf5 upstream. + +Fix a memory leak discovered by syzbot when a file system is corrupted +with an illegally large s_log_groups_per_flex. + +Reported-by: syzbot+aa12d6106ea4ca1b6aae@syzkaller.appspotmail.com +Signed-off-by: Phillip Potter +Cc: stable@kernel.org +Link: https://lore.kernel.org/r/20210412073837.1686-1-phil@philpotter.co.uk +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/mballoc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -2715,7 +2715,7 @@ static int ext4_mb_init_backend(struct s + */ + if (sbi->s_es->s_log_groups_per_flex >= 32) { + ext4_msg(sb, KERN_ERR, "too many log groups per flexible block group"); +- goto err_freesgi; ++ goto err_freebuddy; + } + sbi->s_mb_prefetch = min_t(uint, 1 << sbi->s_es->s_log_groups_per_flex, + BLK_MAX_SEGMENT_SIZE >> (sb->s_blocksize_bits - 9)); diff --git a/queue-5.12/gfs2-fix-scheduling-while-atomic-bug-in-glocks.patch b/queue-5.12/gfs2-fix-scheduling-while-atomic-bug-in-glocks.patch new file mode 100644 index 00000000000..e2c7f020b82 --- /dev/null +++ b/queue-5.12/gfs2-fix-scheduling-while-atomic-bug-in-glocks.patch @@ -0,0 +1,40 @@ +From 20265d9a67e40eafd39a8884658ca2e36f05985d Mon Sep 17 00:00:00 2001 +From: Bob Peterson +Date: Tue, 18 May 2021 09:12:10 -0400 +Subject: gfs2: fix scheduling while atomic bug in glocks + +From: Bob Peterson + +commit 20265d9a67e40eafd39a8884658ca2e36f05985d upstream. + +Before this patch, in the unlikely event that gfs2_glock_dq encountered +a withdraw, it would do a wait_on_bit to wait for its journal to be +recovered, but it never released the glock's spin_lock, which caused a +scheduling-while-atomic error. + +This patch unlocks the lockref spin_lock before waiting for recovery. + +Fixes: 601ef0d52e96 ("gfs2: Force withdraw to replay journals and wait for it to finish") +Cc: stable@vger.kernel.org # v5.7+ +Reported-by: Alexander Aring +Signed-off-by: Bob Peterson +Signed-off-by: Andreas Gruenbacher +Signed-off-by: Greg Kroah-Hartman +--- + fs/gfs2/glock.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/gfs2/glock.c ++++ b/fs/gfs2/glock.c +@@ -1465,9 +1465,11 @@ void gfs2_glock_dq(struct gfs2_holder *g + glock_blocked_by_withdraw(gl) && + gh->gh_gl != sdp->sd_jinode_gl) { + sdp->sd_glock_dqs_held++; ++ spin_unlock(&gl->gl_lockref.lock); + might_sleep(); + wait_on_bit(&sdp->sd_flags, SDF_WITHDRAW_RECOVERY, + TASK_UNINTERRUPTIBLE); ++ spin_lock(&gl->gl_lockref.lock); + } + if (gh->gh_flags & GL_NOCACHE) + handle_callback(gl, LM_ST_UNLOCKED, 0, false); diff --git a/queue-5.12/hid-i2c-hid-skip-elan-power-on-command-after-reset.patch b/queue-5.12/hid-i2c-hid-skip-elan-power-on-command-after-reset.patch new file mode 100644 index 00000000000..b56ae4310c1 --- /dev/null +++ b/queue-5.12/hid-i2c-hid-skip-elan-power-on-command-after-reset.patch @@ -0,0 +1,63 @@ +From ca66a6770bd9d6d99e469debd1c7363ac455daf9 Mon Sep 17 00:00:00 2001 +From: Johnny Chuang +Date: Tue, 13 Apr 2021 09:20:50 +0800 +Subject: HID: i2c-hid: Skip ELAN power-on command after reset + +From: Johnny Chuang + +commit ca66a6770bd9d6d99e469debd1c7363ac455daf9 upstream. + +For ELAN touchscreen, we found our boot code of IC was not flexible enough +to receive and handle this command. +Once the FW main code of our controller is crashed for some reason, +the controller could not be enumerated successfully to be recognized +by the system host. therefore, it lost touch functionality. + +Add quirk for skip send power-on command after reset. +It will impact to ELAN touchscreen and touchpad on HID over I2C projects. + +Fixes: 43b7029f475e ("HID: i2c-hid: Send power-on command after reset"). + +Cc: stable@vger.kernel.org +Signed-off-by: Johnny Chuang +Reviewed-by: Harry Cutts +Reviewed-by: Douglas Anderson +Tested-by: Douglas Anderson +Signed-off-by: Benjamin Tissoires +Signed-off-by: Greg Kroah-Hartman +--- + drivers/hid/i2c-hid/i2c-hid-core.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/drivers/hid/i2c-hid/i2c-hid-core.c ++++ b/drivers/hid/i2c-hid/i2c-hid-core.c +@@ -45,6 +45,7 @@ + #define I2C_HID_QUIRK_BOGUS_IRQ BIT(4) + #define I2C_HID_QUIRK_RESET_ON_RESUME BIT(5) + #define I2C_HID_QUIRK_BAD_INPUT_SIZE BIT(6) ++#define I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET BIT(7) + + + /* flags */ +@@ -178,6 +179,11 @@ static const struct i2c_hid_quirks { + I2C_HID_QUIRK_RESET_ON_RESUME }, + { USB_VENDOR_ID_ITE, I2C_DEVICE_ID_ITE_LENOVO_LEGION_Y720, + I2C_HID_QUIRK_BAD_INPUT_SIZE }, ++ /* ++ * Sending the wakeup after reset actually break ELAN touchscreen controller ++ */ ++ { USB_VENDOR_ID_ELAN, HID_ANY_ID, ++ I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET }, + { 0, 0 } + }; + +@@ -461,7 +467,8 @@ static int i2c_hid_hwreset(struct i2c_cl + } + + /* At least some SIS devices need this after reset */ +- ret = i2c_hid_set_power(client, I2C_HID_PWR_ON); ++ if (!(ihid->quirks & I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET)) ++ ret = i2c_hid_set_power(client, I2C_HID_PWR_ON); + + out_unlock: + mutex_unlock(&ihid->reset_lock); diff --git a/queue-5.12/hid-magicmouse-fix-null-deref-on-disconnect.patch b/queue-5.12/hid-magicmouse-fix-null-deref-on-disconnect.patch new file mode 100644 index 00000000000..eb09119545e --- /dev/null +++ b/queue-5.12/hid-magicmouse-fix-null-deref-on-disconnect.patch @@ -0,0 +1,39 @@ +From 4b4f6cecca446abcb686c6e6c451d4f1ec1a7497 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 17 May 2021 12:04:30 +0200 +Subject: HID: magicmouse: fix NULL-deref on disconnect + +From: Johan Hovold + +commit 4b4f6cecca446abcb686c6e6c451d4f1ec1a7497 upstream. + +Commit 9d7b18668956 ("HID: magicmouse: add support for Apple Magic +Trackpad 2") added a sanity check for an Apple trackpad but returned +success instead of -ENODEV when the check failed. This means that the +remove callback will dereference the never-initialised driver data +pointer when the driver is later unbound (e.g. on USB disconnect). + +Reported-by: syzbot+ee6f6e2e68886ca256a8@syzkaller.appspotmail.com +Fixes: 9d7b18668956 ("HID: magicmouse: add support for Apple Magic Trackpad 2") +Cc: stable@vger.kernel.org # 4.20 +Cc: Claudio Mettler +Cc: Marek Wyborski +Cc: Sean O'Brien +Signed-off-by: Johan Hovold +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman +--- + drivers/hid/hid-magicmouse.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/hid/hid-magicmouse.c ++++ b/drivers/hid/hid-magicmouse.c +@@ -597,7 +597,7 @@ static int magicmouse_probe(struct hid_d + if (id->vendor == USB_VENDOR_ID_APPLE && + id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 && + hdev->type != HID_TYPE_USBMOUSE) +- return 0; ++ return -ENODEV; + + msc = devm_kzalloc(&hdev->dev, sizeof(*msc), GFP_KERNEL); + if (msc == NULL) { diff --git a/queue-5.12/hid-multitouch-require-finger-field-to-mark-win8-reports-as-mt.patch b/queue-5.12/hid-multitouch-require-finger-field-to-mark-win8-reports-as-mt.patch new file mode 100644 index 00000000000..84ac39a3b65 --- /dev/null +++ b/queue-5.12/hid-multitouch-require-finger-field-to-mark-win8-reports-as-mt.patch @@ -0,0 +1,50 @@ +From a2353e3b26012ff43bcdf81d37a3eaddd7ecdbf3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ahelenia=20Ziemia=C5=84ska?= + +Date: Mon, 8 Mar 2021 18:42:03 +0100 +Subject: HID: multitouch: require Finger field to mark Win8 reports as MT +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ahelenia Ziemiańska + +commit a2353e3b26012ff43bcdf81d37a3eaddd7ecdbf3 upstream. + +This effectively changes collection_is_mt from + contact ID in report->field +to + (device is Win8 => collection is finger) && contact ID in report->field + +Some devices erroneously report Pen for fingers, and Win8 stylus-on-touchscreen +devices report contact ID, but mark the accompanying touchscreen device's +collection correctly + +Cc: stable@vger.kernel.org +Signed-off-by: Ahelenia Ziemiańska +Acked-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman +--- + drivers/hid/hid-multitouch.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -604,9 +604,13 @@ static struct mt_report_data *mt_allocat + if (!(HID_MAIN_ITEM_VARIABLE & field->flags)) + continue; + +- for (n = 0; n < field->report_count; n++) { +- if (field->usage[n].hid == HID_DG_CONTACTID) +- rdata->is_mt_collection = true; ++ if (field->logical == HID_DG_FINGER || td->hdev->group != HID_GROUP_MULTITOUCH_WIN_8) { ++ for (n = 0; n < field->report_count; n++) { ++ if (field->usage[n].hid == HID_DG_CONTACTID) { ++ rdata->is_mt_collection = true; ++ break; ++ } ++ } + } + } + diff --git a/queue-5.12/net-caif-add-proper-error-handling.patch b/queue-5.12/net-caif-add-proper-error-handling.patch new file mode 100644 index 00000000000..b7246a16b50 --- /dev/null +++ b/queue-5.12/net-caif-add-proper-error-handling.patch @@ -0,0 +1,152 @@ +From a2805dca5107d5603f4bbc027e81e20d93476e96 Mon Sep 17 00:00:00 2001 +From: Pavel Skripkin +Date: Thu, 3 Jun 2021 19:38:51 +0300 +Subject: net: caif: add proper error handling + +From: Pavel Skripkin + +commit a2805dca5107d5603f4bbc027e81e20d93476e96 upstream. + +caif_enroll_dev() can fail in some cases. Ingnoring +these cases can lead to memory leak due to not assigning +link_support pointer to anywhere. + +Fixes: 7c18d2205ea7 ("caif: Restructure how link caif link layer enroll") +Cc: stable@vger.kernel.org +Signed-off-by: Pavel Skripkin +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/net/caif/caif_dev.h | 2 +- + include/net/caif/cfcnfg.h | 2 +- + net/caif/caif_dev.c | 8 +++++--- + net/caif/cfcnfg.c | 16 +++++++++++----- + 4 files changed, 18 insertions(+), 10 deletions(-) + +--- a/include/net/caif/caif_dev.h ++++ b/include/net/caif/caif_dev.h +@@ -119,7 +119,7 @@ void caif_free_client(struct cflayer *ad + * The link_support layer is used to add any Link Layer specific + * framing. + */ +-void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, ++int caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, + struct cflayer *link_support, int head_room, + struct cflayer **layer, int (**rcv_func)( + struct sk_buff *, struct net_device *, +--- a/include/net/caif/cfcnfg.h ++++ b/include/net/caif/cfcnfg.h +@@ -62,7 +62,7 @@ void cfcnfg_remove(struct cfcnfg *cfg); + * @fcs: Specify if checksum is used in CAIF Framing Layer. + * @head_room: Head space needed by link specific protocol. + */ +-void ++int + cfcnfg_add_phy_layer(struct cfcnfg *cnfg, + struct net_device *dev, struct cflayer *phy_layer, + enum cfcnfg_phy_preference pref, +--- a/net/caif/caif_dev.c ++++ b/net/caif/caif_dev.c +@@ -308,7 +308,7 @@ static void dev_flowctrl(struct net_devi + caifd_put(caifd); + } + +-void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, ++int caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, + struct cflayer *link_support, int head_room, + struct cflayer **layer, + int (**rcv_func)(struct sk_buff *, struct net_device *, +@@ -319,11 +319,12 @@ void caif_enroll_dev(struct net_device * + enum cfcnfg_phy_preference pref; + struct cfcnfg *cfg = get_cfcnfg(dev_net(dev)); + struct caif_device_entry_list *caifdevs; ++ int res; + + caifdevs = caif_device_list(dev_net(dev)); + caifd = caif_device_alloc(dev); + if (!caifd) +- return; ++ return -ENOMEM; + *layer = &caifd->layer; + spin_lock_init(&caifd->flow_lock); + +@@ -344,7 +345,7 @@ void caif_enroll_dev(struct net_device * + strlcpy(caifd->layer.name, dev->name, + sizeof(caifd->layer.name)); + caifd->layer.transmit = transmit; +- cfcnfg_add_phy_layer(cfg, ++ res = cfcnfg_add_phy_layer(cfg, + dev, + &caifd->layer, + pref, +@@ -354,6 +355,7 @@ void caif_enroll_dev(struct net_device * + mutex_unlock(&caifdevs->lock); + if (rcv_func) + *rcv_func = receive; ++ return res; + } + EXPORT_SYMBOL(caif_enroll_dev); + +--- a/net/caif/cfcnfg.c ++++ b/net/caif/cfcnfg.c +@@ -450,7 +450,7 @@ unlock: + rcu_read_unlock(); + } + +-void ++int + cfcnfg_add_phy_layer(struct cfcnfg *cnfg, + struct net_device *dev, struct cflayer *phy_layer, + enum cfcnfg_phy_preference pref, +@@ -459,7 +459,7 @@ cfcnfg_add_phy_layer(struct cfcnfg *cnfg + { + struct cflayer *frml; + struct cfcnfg_phyinfo *phyinfo = NULL; +- int i; ++ int i, res = 0; + u8 phyid; + + mutex_lock(&cnfg->lock); +@@ -473,12 +473,15 @@ cfcnfg_add_phy_layer(struct cfcnfg *cnfg + goto got_phyid; + } + pr_warn("Too many CAIF Link Layers (max 6)\n"); ++ res = -EEXIST; + goto out; + + got_phyid: + phyinfo = kzalloc(sizeof(struct cfcnfg_phyinfo), GFP_ATOMIC); +- if (!phyinfo) ++ if (!phyinfo) { ++ res = -ENOMEM; + goto out_err; ++ } + + phy_layer->id = phyid; + phyinfo->pref = pref; +@@ -492,8 +495,10 @@ got_phyid: + + frml = cffrml_create(phyid, fcs); + +- if (!frml) ++ if (!frml) { ++ res = -ENOMEM; + goto out_err; ++ } + phyinfo->frm_layer = frml; + layer_set_up(frml, cnfg->mux); + +@@ -511,11 +516,12 @@ got_phyid: + list_add_rcu(&phyinfo->node, &cnfg->phys); + out: + mutex_unlock(&cnfg->lock); +- return; ++ return res; + + out_err: + kfree(phyinfo); + mutex_unlock(&cnfg->lock); ++ return res; + } + EXPORT_SYMBOL(cfcnfg_add_phy_layer); + diff --git a/queue-5.12/net-caif-added-cfserl_release-function.patch b/queue-5.12/net-caif-added-cfserl_release-function.patch new file mode 100644 index 00000000000..113cf4ec852 --- /dev/null +++ b/queue-5.12/net-caif-added-cfserl_release-function.patch @@ -0,0 +1,42 @@ +From bce130e7f392ddde8cfcb09927808ebd5f9c8669 Mon Sep 17 00:00:00 2001 +From: Pavel Skripkin +Date: Thu, 3 Jun 2021 19:38:12 +0300 +Subject: net: caif: added cfserl_release function + +From: Pavel Skripkin + +commit bce130e7f392ddde8cfcb09927808ebd5f9c8669 upstream. + +Added cfserl_release() function. + +Cc: stable@vger.kernel.org +Signed-off-by: Pavel Skripkin +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/net/caif/cfserl.h | 1 + + net/caif/cfserl.c | 5 +++++ + 2 files changed, 6 insertions(+) + +--- a/include/net/caif/cfserl.h ++++ b/include/net/caif/cfserl.h +@@ -9,4 +9,5 @@ + #include + + struct cflayer *cfserl_create(int instance, bool use_stx); ++void cfserl_release(struct cflayer *layer); + #endif +--- a/net/caif/cfserl.c ++++ b/net/caif/cfserl.c +@@ -31,6 +31,11 @@ static int cfserl_transmit(struct cflaye + static void cfserl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, + int phyid); + ++void cfserl_release(struct cflayer *layer) ++{ ++ kfree(layer); ++} ++ + struct cflayer *cfserl_create(int instance, bool use_stx) + { + struct cfserl *this = kzalloc(sizeof(struct cfserl), GFP_ATOMIC); diff --git a/queue-5.12/net-caif-fix-memory-leak-in-caif_device_notify.patch b/queue-5.12/net-caif-fix-memory-leak-in-caif_device_notify.patch new file mode 100644 index 00000000000..db0db894744 --- /dev/null +++ b/queue-5.12/net-caif-fix-memory-leak-in-caif_device_notify.patch @@ -0,0 +1,46 @@ +From b53558a950a89824938e9811eddfc8efcd94e1bb Mon Sep 17 00:00:00 2001 +From: Pavel Skripkin +Date: Thu, 3 Jun 2021 19:39:11 +0300 +Subject: net: caif: fix memory leak in caif_device_notify + +From: Pavel Skripkin + +commit b53558a950a89824938e9811eddfc8efcd94e1bb upstream. + +In case of caif_enroll_dev() fail, allocated +link_support won't be assigned to the corresponding +structure. So simply free allocated pointer in case +of error + +Fixes: 7c18d2205ea7 ("caif: Restructure how link caif link layer enroll") +Cc: stable@vger.kernel.org +Reported-and-tested-by: syzbot+7ec324747ce876a29db6@syzkaller.appspotmail.com +Signed-off-by: Pavel Skripkin +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/caif/caif_dev.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/net/caif/caif_dev.c ++++ b/net/caif/caif_dev.c +@@ -370,6 +370,7 @@ static int caif_device_notify(struct not + struct cflayer *layer, *link_support; + int head_room = 0; + struct caif_device_entry_list *caifdevs; ++ int res; + + cfg = get_cfcnfg(dev_net(dev)); + caifdevs = caif_device_list(dev_net(dev)); +@@ -395,8 +396,10 @@ static int caif_device_notify(struct not + break; + } + } +- caif_enroll_dev(dev, caifdev, link_support, head_room, ++ res = caif_enroll_dev(dev, caifdev, link_support, head_room, + &layer, NULL); ++ if (res) ++ cfserl_release(link_support); + caifdev->flowctrl = dev_flowctrl; + break; + diff --git a/queue-5.12/net-caif-fix-memory-leak-in-cfusbl_device_notify.patch b/queue-5.12/net-caif-fix-memory-leak-in-cfusbl_device_notify.patch new file mode 100644 index 00000000000..f0caac0693c --- /dev/null +++ b/queue-5.12/net-caif-fix-memory-leak-in-cfusbl_device_notify.patch @@ -0,0 +1,68 @@ +From 7f5d86669fa4d485523ddb1d212e0a2d90bd62bb Mon Sep 17 00:00:00 2001 +From: Pavel Skripkin +Date: Thu, 3 Jun 2021 19:39:35 +0300 +Subject: net: caif: fix memory leak in cfusbl_device_notify + +From: Pavel Skripkin + +commit 7f5d86669fa4d485523ddb1d212e0a2d90bd62bb upstream. + +In case of caif_enroll_dev() fail, allocated +link_support won't be assigned to the corresponding +structure. So simply free allocated pointer in case +of error. + +Fixes: 7ad65bf68d70 ("caif: Add support for CAIF over CDC NCM USB interface") +Cc: stable@vger.kernel.org +Signed-off-by: Pavel Skripkin +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/caif/caif_usb.c | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +--- a/net/caif/caif_usb.c ++++ b/net/caif/caif_usb.c +@@ -115,6 +115,11 @@ static struct cflayer *cfusbl_create(int + return (struct cflayer *) this; + } + ++static void cfusbl_release(struct cflayer *layer) ++{ ++ kfree(layer); ++} ++ + static struct packet_type caif_usb_type __read_mostly = { + .type = cpu_to_be16(ETH_P_802_EX1), + }; +@@ -127,6 +132,7 @@ static int cfusbl_device_notify(struct n + struct cflayer *layer, *link_support; + struct usbnet *usbnet; + struct usb_device *usbdev; ++ int res; + + /* Check whether we have a NCM device, and find its VID/PID. */ + if (!(dev->dev.parent && dev->dev.parent->driver && +@@ -169,8 +175,11 @@ static int cfusbl_device_notify(struct n + if (dev->num_tx_queues > 1) + pr_warn("USB device uses more than one tx queue\n"); + +- caif_enroll_dev(dev, &common, link_support, CFUSB_MAX_HEADLEN, ++ res = caif_enroll_dev(dev, &common, link_support, CFUSB_MAX_HEADLEN, + &layer, &caif_usb_type.func); ++ if (res) ++ goto err; ++ + if (!pack_added) + dev_add_pack(&caif_usb_type); + pack_added = true; +@@ -178,6 +187,9 @@ static int cfusbl_device_notify(struct n + strlcpy(layer->name, dev->name, sizeof(layer->name)); + + return 0; ++err: ++ cfusbl_release(link_support); ++ return res; + } + + static struct notifier_block caif_device_notifier = { diff --git a/queue-5.12/net-kcm-fix-memory-leak-in-kcm_sendmsg.patch b/queue-5.12/net-kcm-fix-memory-leak-in-kcm_sendmsg.patch new file mode 100644 index 00000000000..691317364de --- /dev/null +++ b/queue-5.12/net-kcm-fix-memory-leak-in-kcm_sendmsg.patch @@ -0,0 +1,52 @@ +From c47cc304990a2813995b1a92bbc11d0bb9a19ea9 Mon Sep 17 00:00:00 2001 +From: Pavel Skripkin +Date: Wed, 2 Jun 2021 22:26:40 +0300 +Subject: net: kcm: fix memory leak in kcm_sendmsg + +From: Pavel Skripkin + +commit c47cc304990a2813995b1a92bbc11d0bb9a19ea9 upstream. + +Syzbot reported memory leak in kcm_sendmsg()[1]. +The problem was in non-freed frag_list in case of error. + +In the while loop: + + if (head == skb) + skb_shinfo(head)->frag_list = tskb; + else + skb->next = tskb; + +frag_list filled with skbs, but nothing was freeing them. + +backtrace: + [<0000000094c02615>] __alloc_skb+0x5e/0x250 net/core/skbuff.c:198 + [<00000000e5386cbd>] alloc_skb include/linux/skbuff.h:1083 [inline] + [<00000000e5386cbd>] kcm_sendmsg+0x3b6/0xa50 net/kcm/kcmsock.c:967 [1] + [<00000000f1613a8a>] sock_sendmsg_nosec net/socket.c:652 [inline] + [<00000000f1613a8a>] sock_sendmsg+0x4c/0x60 net/socket.c:672 + +Reported-and-tested-by: syzbot+b039f5699bd82e1fb011@syzkaller.appspotmail.com +Fixes: ab7ac4eb9832 ("kcm: Kernel Connection Multiplexor module") +Cc: stable@vger.kernel.org +Signed-off-by: Pavel Skripkin +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/kcm/kcmsock.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/net/kcm/kcmsock.c ++++ b/net/kcm/kcmsock.c +@@ -1066,6 +1066,11 @@ out_error: + goto partial_message; + } + ++ if (skb_has_frag_list(head)) { ++ kfree_skb_list(skb_shinfo(head)->frag_list); ++ skb_shinfo(head)->frag_list = NULL; ++ } ++ + if (head != kcm->seq_skb) + kfree_skb(head); + diff --git a/queue-5.12/series b/queue-5.12/series index c098ea4936f..71e6166eaa8 100644 --- a/queue-5.12/series +++ b/queue-5.12/series @@ -100,3 +100,22 @@ wireguard-allowedips-initialize-list-head-in-selftest.patch wireguard-allowedips-remove-nodes-in-o-1.patch wireguard-allowedips-allocate-nodes-in-kmem_cache.patch wireguard-allowedips-free-empty-intermediate-nodes-when-removing-single-node.patch +net-kcm-fix-memory-leak-in-kcm_sendmsg.patch +net-caif-added-cfserl_release-function.patch +net-caif-add-proper-error-handling.patch +net-caif-fix-memory-leak-in-caif_device_notify.patch +net-caif-fix-memory-leak-in-cfusbl_device_notify.patch +hid-i2c-hid-skip-elan-power-on-command-after-reset.patch +hid-magicmouse-fix-null-deref-on-disconnect.patch +hid-multitouch-require-finger-field-to-mark-win8-reports-as-mt.patch +gfs2-fix-scheduling-while-atomic-bug-in-glocks.patch +alsa-timer-fix-master-timer-notification.patch +alsa-hda-fix-for-mute-key-led-for-hp-pavilion-15-ck0xx.patch +alsa-hda-update-the-power_state-during-the-direct-complete.patch +arm-dts-imx6dl-yapp4-fix-rgmii-connection-to-qca8334-switch.patch +arm-dts-imx6q-dhcom-add-pu-vdd1p1-vdd2p5-regulators.patch +ext4-fix-memory-leak-in-ext4_fill_super.patch +ext4-fix-bug-on-in-ext4_es_cache_extent-as-ext4_split_extent_at-failed.patch +ext4-fix-fast-commit-alignment-issues.patch +ext4-fix-memory-leak-in-ext4_mb_init_backend-on-error-path.patch +ext4-fix-accessing-uninit-percpu-counter-variable-with-fast_commit.patch