From: Greg Kroah-Hartman Date: Mon, 9 Mar 2020 18:30:40 +0000 (+0100) Subject: 5.5-stable patches X-Git-Tag: v4.4.216~56 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=44920f6fe2e5c4e4340da4501fcc54044aba4a8f;p=thirdparty%2Fkernel%2Fstable-queue.git 5.5-stable patches added patches: alsa-hda-realtek-add-headset-button-supported-for-thinkpad-x1.patch alsa-hda-realtek-add-headset-mic-supported.patch alsa-hda-realtek-enable-the-headset-of-asus-b9450fa-with-alc294.patch alsa-hda-realtek-fix-a-regression-for-mute-led-on-lenovo-carbon-x1.patch alsa-hda-realtek-fix-silent-output-on-gigabyte-x570-aorus-master.patch binder-prevent-uaf-for-binderfs-devices-ii.patch binder-prevent-uaf-for-binderfs-devices.patch cifs-don-t-leak-eagain-for-stat-during-reconnect.patch cifs-fix-rename-by-ensuring-source-handle-opened-with-delete-bit.patch driver-core-call-sync_state-even-if-supplier-has-no-consumers.patch firmware-imx-scu-ensure-sequential-tx.patch --- diff --git a/queue-5.5/alsa-hda-realtek-add-headset-button-supported-for-thinkpad-x1.patch b/queue-5.5/alsa-hda-realtek-add-headset-button-supported-for-thinkpad-x1.patch new file mode 100644 index 00000000000..974f25a1f58 --- /dev/null +++ b/queue-5.5/alsa-hda-realtek-add-headset-button-supported-for-thinkpad-x1.patch @@ -0,0 +1,58 @@ +From 76f7dec08fd64e9e3ad0810a1a8a60b0a846d348 Mon Sep 17 00:00:00 2001 +From: Kailang Yang +Date: Mon, 10 Feb 2020 16:30:26 +0800 +Subject: ALSA: hda/realtek - Add Headset Button supported for ThinkPad X1 + +From: Kailang Yang + +commit 76f7dec08fd64e9e3ad0810a1a8a60b0a846d348 upstream. + +ThinkPad want to support Headset Button control. +This patch will enable it. + +Signed-off-by: Kailang Yang +Cc: +Link: https://lore.kernel.org/r/7f0b7128f40f41f6b5582ff610adc33d@realtek.com +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/hda/patch_realtek.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -5920,7 +5920,7 @@ enum { + ALC289_FIXUP_DUAL_SPK, + ALC294_FIXUP_SPK2_TO_DAC1, + ALC294_FIXUP_ASUS_DUAL_SPK, +- ++ ALC285_FIXUP_THINKPAD_HEADSET_JACK, + }; + + static const struct hda_fixup alc269_fixups[] = { +@@ -7040,7 +7040,12 @@ static const struct hda_fixup alc269_fix + .chained = true, + .chain_id = ALC294_FIXUP_SPK2_TO_DAC1 + }, +- ++ [ALC285_FIXUP_THINKPAD_HEADSET_JACK] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc_fixup_headset_jack, ++ .chained = true, ++ .chain_id = ALC285_FIXUP_SPEAKER2_TO_DAC1 ++ }, + }; + + static const struct snd_pci_quirk alc269_fixup_tbl[] = { +@@ -7276,8 +7281,8 @@ static const struct snd_pci_quirk alc269 + SND_PCI_QUIRK(0x17aa, 0x224c, "Thinkpad", ALC298_FIXUP_TPT470_DOCK), + SND_PCI_QUIRK(0x17aa, 0x224d, "Thinkpad", ALC298_FIXUP_TPT470_DOCK), + SND_PCI_QUIRK(0x17aa, 0x225d, "Thinkpad T480", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), +- SND_PCI_QUIRK(0x17aa, 0x2292, "Thinkpad X1 Yoga 7th", ALC285_FIXUP_SPEAKER2_TO_DAC1), +- SND_PCI_QUIRK(0x17aa, 0x2293, "Thinkpad X1 Carbon 7th", ALC285_FIXUP_SPEAKER2_TO_DAC1), ++ SND_PCI_QUIRK(0x17aa, 0x2292, "Thinkpad X1 Yoga 7th", ALC285_FIXUP_THINKPAD_HEADSET_JACK), ++ SND_PCI_QUIRK(0x17aa, 0x2293, "Thinkpad X1 Carbon 7th", ALC285_FIXUP_THINKPAD_HEADSET_JACK), + SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), + SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), + SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), diff --git a/queue-5.5/alsa-hda-realtek-add-headset-mic-supported.patch b/queue-5.5/alsa-hda-realtek-add-headset-mic-supported.patch new file mode 100644 index 00000000000..497fd9d0ea9 --- /dev/null +++ b/queue-5.5/alsa-hda-realtek-add-headset-mic-supported.patch @@ -0,0 +1,34 @@ +From 78def224f59c05d00e815be946ec229719ccf377 Mon Sep 17 00:00:00 2001 +From: Kailang Yang +Date: Thu, 20 Feb 2020 15:21:54 +0800 +Subject: ALSA: hda/realtek - Add Headset Mic supported + +From: Kailang Yang + +commit 78def224f59c05d00e815be946ec229719ccf377 upstream. + +Dell desktop platform supported headset Mic. +Add pin verb to enable headset Mic. +This platform only support fixed type headset for Iphone type. + +Signed-off-by: Kailang Yang +Cc: +Link: https://lore.kernel.org/r/b9da28d772ef43088791b0f3675929e7@realtek.com +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/hda/patch_realtek.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -7115,6 +7115,8 @@ static const struct snd_pci_quirk alc269 + SND_PCI_QUIRK(0x1028, 0x0935, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB), + SND_PCI_QUIRK(0x1028, 0x097e, "Dell Precision", ALC289_FIXUP_DUAL_SPK), + SND_PCI_QUIRK(0x1028, 0x097d, "Dell Precision", ALC289_FIXUP_DUAL_SPK), ++ SND_PCI_QUIRK(0x1028, 0x098d, "Dell Precision", ALC233_FIXUP_ASUS_MIC_NO_PRESENCE), ++ SND_PCI_QUIRK(0x1028, 0x09bf, "Dell Precision", ALC233_FIXUP_ASUS_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), diff --git a/queue-5.5/alsa-hda-realtek-enable-the-headset-of-asus-b9450fa-with-alc294.patch b/queue-5.5/alsa-hda-realtek-enable-the-headset-of-asus-b9450fa-with-alc294.patch new file mode 100644 index 00000000000..32b72ce50a4 --- /dev/null +++ b/queue-5.5/alsa-hda-realtek-enable-the-headset-of-asus-b9450fa-with-alc294.patch @@ -0,0 +1,59 @@ +From 8b33a134a9cc2a501f8fc731d91caef39237d495 Mon Sep 17 00:00:00 2001 +From: Jian-Hong Pan +Date: Tue, 25 Feb 2020 15:29:21 +0800 +Subject: ALSA: hda/realtek - Enable the headset of ASUS B9450FA with ALC294 + +From: Jian-Hong Pan + +commit 8b33a134a9cc2a501f8fc731d91caef39237d495 upstream. + +A headset on the laptop like ASUS B9450FA does not work, until quirk +ALC294_FIXUP_ASUS_HPE is applied. + +Signed-off-by: Jian-Hong Pan +Signed-off-by: Kailang Yang +Cc: +Link: https://lore.kernel.org/r/20200225072920.109199-1-jian-hong@endlessm.com +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/hda/patch_realtek.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -5922,6 +5922,7 @@ enum { + ALC294_FIXUP_SPK2_TO_DAC1, + ALC294_FIXUP_ASUS_DUAL_SPK, + ALC285_FIXUP_THINKPAD_HEADSET_JACK, ++ ALC294_FIXUP_ASUS_HPE, + }; + + static const struct hda_fixup alc269_fixups[] = { +@@ -7049,6 +7050,17 @@ static const struct hda_fixup alc269_fix + .chained = true, + .chain_id = ALC285_FIXUP_SPEAKER2_TO_DAC1 + }, ++ [ALC294_FIXUP_ASUS_HPE] = { ++ .type = HDA_FIXUP_VERBS, ++ .v.verbs = (const struct hda_verb[]) { ++ /* Set EAPD high */ ++ { 0x20, AC_VERB_SET_COEF_INDEX, 0x0f }, ++ { 0x20, AC_VERB_SET_PROC_COEF, 0x7774 }, ++ { } ++ }, ++ .chained = true, ++ .chain_id = ALC294_FIXUP_ASUS_HEADSET_MIC ++ }, + }; + + static const struct snd_pci_quirk alc269_fixup_tbl[] = { +@@ -7214,6 +7226,7 @@ static const struct snd_pci_quirk alc269 + SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), + SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK), + SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC), ++ SND_PCI_QUIRK(0x1043, 0x19ce, "ASUS B9450FA", ALC294_FIXUP_ASUS_HPE), + SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), + SND_PCI_QUIRK(0x1043, 0x1a30, "ASUS X705UD", ALC256_FIXUP_ASUS_MIC), + SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC), diff --git a/queue-5.5/alsa-hda-realtek-fix-a-regression-for-mute-led-on-lenovo-carbon-x1.patch b/queue-5.5/alsa-hda-realtek-fix-a-regression-for-mute-led-on-lenovo-carbon-x1.patch new file mode 100644 index 00000000000..05d913c38f5 --- /dev/null +++ b/queue-5.5/alsa-hda-realtek-fix-a-regression-for-mute-led-on-lenovo-carbon-x1.patch @@ -0,0 +1,34 @@ +From c37c0ab029569a75fd180edb03d411e7a28a936f Mon Sep 17 00:00:00 2001 +From: Hui Wang +Date: Wed, 19 Feb 2020 13:23:06 +0800 +Subject: ALSA: hda/realtek - Fix a regression for mute led on Lenovo Carbon X1 + +From: Hui Wang + +commit c37c0ab029569a75fd180edb03d411e7a28a936f upstream. + +Need to chain the THINKPAD_ACPI, otherwise the mute led will not +work. + +Fixes: d2cd795c4ece ("ALSA: hda - fixup for the bass speaker on Lenovo Carbon X1 7th gen") +Cc: +Signed-off-by: Hui Wang +Link: https://lore.kernel.org/r/20200219052306.24935-1-hui.wang@canonical.com +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/hda/patch_realtek.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -6684,6 +6684,8 @@ static const struct hda_fixup alc269_fix + [ALC285_FIXUP_SPEAKER2_TO_DAC1] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc285_fixup_speaker2_to_dac1, ++ .chained = true, ++ .chain_id = ALC269_FIXUP_THINKPAD_ACPI + }, + [ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER] = { + .type = HDA_FIXUP_PINS, diff --git a/queue-5.5/alsa-hda-realtek-fix-silent-output-on-gigabyte-x570-aorus-master.patch b/queue-5.5/alsa-hda-realtek-fix-silent-output-on-gigabyte-x570-aorus-master.patch new file mode 100644 index 00000000000..f59ea3b4722 --- /dev/null +++ b/queue-5.5/alsa-hda-realtek-fix-silent-output-on-gigabyte-x570-aorus-master.patch @@ -0,0 +1,34 @@ +From 0d45e86d2267d5bdf7bbb631499788da1c27ceb2 Mon Sep 17 00:00:00 2001 +From: Christian Lachner +Date: Sun, 23 Feb 2020 10:24:16 +0100 +Subject: ALSA: hda/realtek - Fix silent output on Gigabyte X570 Aorus Master + +From: Christian Lachner + +commit 0d45e86d2267d5bdf7bbb631499788da1c27ceb2 upstream. + +The Gigabyte X570 Aorus Master motherboard with ALC1220 codec +requires a similar workaround for Clevo laptops to enforce the +DAC/mixer connection path. Set up a quirk entry for that. + +BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=205275 +Signed-off-by: Christian Lachner +Cc: +Link: https://lore.kernel.org/r/20200223092416.15016-2-gladiac@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 +@@ -2447,6 +2447,7 @@ static const struct snd_pci_quirk alc882 + SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD), + SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE), + SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS), ++ SND_PCI_QUIRK(0x1458, 0xa0cd, "Gigabyte X570 Aorus Master", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1462, 0x1276, "MSI-GL73", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1462, 0x1293, "MSI-GP65", ALC1220_FIXUP_CLEVO_P950), diff --git a/queue-5.5/binder-prevent-uaf-for-binderfs-devices-ii.patch b/queue-5.5/binder-prevent-uaf-for-binderfs-devices-ii.patch new file mode 100644 index 00000000000..f2752eef3b0 --- /dev/null +++ b/queue-5.5/binder-prevent-uaf-for-binderfs-devices-ii.patch @@ -0,0 +1,216 @@ +From f0fe2c0f050d31babcad7d65f1d550d462a40064 Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Tue, 3 Mar 2020 17:43:40 +0100 +Subject: binder: prevent UAF for binderfs devices II + +From: Christian Brauner + +commit f0fe2c0f050d31babcad7d65f1d550d462a40064 upstream. + +This is a necessary follow up to the first fix I proposed and we merged +in 2669b8b0c79 ("binder: prevent UAF for binderfs devices"). I have been +overly optimistic that the simple fix I proposed would work. But alas, +ihold() + iput() won't work since the inodes won't survive the +destruction of the superblock. +So all we get with my prior fix is a different race with a tinier +race-window but it doesn't solve the issue. Fwiw, the problem lies with +generic_shutdown_super(). It even has this cozy Al-style comment: + + if (!list_empty(&sb->s_inodes)) { + printk("VFS: Busy inodes after unmount of %s. " + "Self-destruct in 5 seconds. Have a nice day...\n", + sb->s_id); + } + +On binder_release(), binder_defer_work(proc, BINDER_DEFERRED_RELEASE) is +called which punts the actual cleanup operation to a workqueue. At some +point, binder_deferred_func() will be called which will end up calling +binder_deferred_release() which will retrieve and cleanup the +binder_context attach to this struct binder_proc. + +If we trace back where this binder_context is attached to binder_proc we +see that it is set in binder_open() and is taken from the struct +binder_device it is associated with. This obviously assumes that the +struct binder_device that context is attached to is _never_ freed. While +that might be true for devtmpfs binder devices it is most certainly +wrong for binderfs binder devices. + +So, assume binder_open() is called on a binderfs binder devices. We now +stash away the struct binder_context associated with that struct +binder_devices: + proc->context = &binder_dev->context; + /* binderfs stashes devices in i_private */ + if (is_binderfs_device(nodp)) { + binder_dev = nodp->i_private; + info = nodp->i_sb->s_fs_info; + binder_binderfs_dir_entry_proc = info->proc_log_dir; + } else { + . + . + . + proc->context = &binder_dev->context; + +Now let's assume that the binderfs instance for that binder devices is +shutdown via umount() and/or the mount namespace associated with it goes +away. As long as there is still an fd open for that binderfs binder +device things are fine. But let's assume we now close the last fd for +that binderfs binder device. Now binder_release() is called and punts to +the workqueue. Assume that the workqueue has quite a bit of stuff to do +and doesn't get to cleaning up the struct binder_proc and the associated +struct binder_context with it for that binderfs binder device right +away. In the meantime, the VFS is killing the super block and is +ultimately calling sb->evict_inode() which means it will call +binderfs_evict_inode() which does: + +static void binderfs_evict_inode(struct inode *inode) +{ + struct binder_device *device = inode->i_private; + struct binderfs_info *info = BINDERFS_I(inode); + + clear_inode(inode); + + if (!S_ISCHR(inode->i_mode) || !device) + return; + + mutex_lock(&binderfs_minors_mutex); + --info->device_count; + ida_free(&binderfs_minors, device->miscdev.minor); + mutex_unlock(&binderfs_minors_mutex); + + kfree(device->context.name); + kfree(device); +} + +thereby freeing the struct binder_device including struct +binder_context. + +Now the workqueue finally has time to get around to cleaning up struct +binder_proc and is now trying to access the associate struct +binder_context. Since it's already freed it will OOPs. + +Fix this by introducing a refounct on binder devices. + +This is an alternative fix to 51d8a7eca677 ("binder: prevent UAF read in +print_binder_transaction_log_entry()"). + +Fixes: 3ad20fe393b3 ("binder: implement binderfs") +Fixes: 2669b8b0c798 ("binder: prevent UAF for binderfs devices") +Fixes: 03e2e07e3814 ("binder: Make transaction_log available in binderfs") +Related : 51d8a7eca677 ("binder: prevent UAF read in print_binder_transaction_log_entry()") +Cc: stable@vger.kernel.org +Signed-off-by: Christian Brauner +Acked-by: Todd Kjos +Link: https://lore.kernel.org/r/20200303164340.670054-1-christian.brauner@ubuntu.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/android/binder.c | 12 +++++++++--- + drivers/android/binder_internal.h | 15 ++------------- + drivers/android/binderfs.c | 7 +++++-- + 3 files changed, 16 insertions(+), 18 deletions(-) + +--- a/drivers/android/binder.c ++++ b/drivers/android/binder.c +@@ -5219,13 +5219,14 @@ static int binder_open(struct inode *nod + proc->default_priority = task_nice(current); + /* binderfs stashes devices in i_private */ + if (is_binderfs_device(nodp)) { +- binder_dev = binderfs_device_get(nodp->i_private); ++ binder_dev = nodp->i_private; + info = nodp->i_sb->s_fs_info; + binder_binderfs_dir_entry_proc = info->proc_log_dir; + } else { + binder_dev = container_of(filp->private_data, + struct binder_device, miscdev); + } ++ refcount_inc(&binder_dev->ref); + proc->context = &binder_dev->context; + binder_alloc_init(&proc->alloc); + +@@ -5420,6 +5421,12 @@ static void binder_deferred_release(stru + context->binder_context_mgr_node = NULL; + } + mutex_unlock(&context->context_mgr_node_lock); ++ device = container_of(proc->context, struct binder_device, context); ++ if (refcount_dec_and_test(&device->ref)) { ++ kfree(context->name); ++ kfree(device); ++ } ++ proc->context = NULL; + binder_inner_proc_lock(proc); + /* + * Make sure proc stays alive after we +@@ -5483,8 +5490,6 @@ static void binder_deferred_release(stru + outgoing_refs, active_transactions); + + binder_proc_dec_tmpref(proc); +- device = container_of(proc->context, struct binder_device, context); +- binderfs_device_put(device); + } + + static void binder_deferred_func(struct work_struct *work) +@@ -6078,6 +6083,7 @@ static int __init init_binder_device(con + binder_device->miscdev.minor = MISC_DYNAMIC_MINOR; + binder_device->miscdev.name = name; + ++ refcount_set(&binder_device->ref, 1); + binder_device->context.binder_context_mgr_uid = INVALID_UID; + binder_device->context.name = name; + mutex_init(&binder_device->context.context_mgr_node_lock); +--- a/drivers/android/binder_internal.h ++++ b/drivers/android/binder_internal.h +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -33,21 +34,9 @@ struct binder_device { + struct miscdevice miscdev; + struct binder_context context; + struct inode *binderfs_inode; ++ refcount_t ref; + }; + +-static inline struct binder_device *binderfs_device_get(struct binder_device *dev) +-{ +- if (dev->binderfs_inode) +- ihold(dev->binderfs_inode); +- return dev; +-} +- +-static inline void binderfs_device_put(struct binder_device *dev) +-{ +- if (dev->binderfs_inode) +- iput(dev->binderfs_inode); +-} +- + /** + * binderfs_mount_opts - mount options for binderfs + * @max: maximum number of allocatable binderfs binder devices +--- a/drivers/android/binderfs.c ++++ b/drivers/android/binderfs.c +@@ -154,6 +154,7 @@ static int binderfs_binder_device_create + if (!name) + goto err; + ++ refcount_set(&device->ref, 1); + device->binderfs_inode = inode; + device->context.binder_context_mgr_uid = INVALID_UID; + device->context.name = name; +@@ -257,8 +258,10 @@ static void binderfs_evict_inode(struct + ida_free(&binderfs_minors, device->miscdev.minor); + mutex_unlock(&binderfs_minors_mutex); + +- kfree(device->context.name); +- kfree(device); ++ if (refcount_dec_and_test(&device->ref)) { ++ kfree(device->context.name); ++ kfree(device); ++ } + } + + /** diff --git a/queue-5.5/binder-prevent-uaf-for-binderfs-devices.patch b/queue-5.5/binder-prevent-uaf-for-binderfs-devices.patch new file mode 100644 index 00000000000..fd588f150b6 --- /dev/null +++ b/queue-5.5/binder-prevent-uaf-for-binderfs-devices.patch @@ -0,0 +1,147 @@ +From 2669b8b0c798fbe1a31d49e07aa33233d469ad9b Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Fri, 21 Feb 2020 19:01:24 +0100 +Subject: binder: prevent UAF for binderfs devices + +From: Christian Brauner + +commit 2669b8b0c798fbe1a31d49e07aa33233d469ad9b upstream. + +On binder_release(), binder_defer_work(proc, BINDER_DEFERRED_RELEASE) is +called which punts the actual cleanup operation to a workqueue. At some +point, binder_deferred_func() will be called which will end up calling +binder_deferred_release() which will retrieve and cleanup the +binder_context attach to this struct binder_proc. + +If we trace back where this binder_context is attached to binder_proc we +see that it is set in binder_open() and is taken from the struct +binder_device it is associated with. This obviously assumes that the +struct binder_device that context is attached to is _never_ freed. While +that might be true for devtmpfs binder devices it is most certainly +wrong for binderfs binder devices. + +So, assume binder_open() is called on a binderfs binder devices. We now +stash away the struct binder_context associated with that struct +binder_devices: + proc->context = &binder_dev->context; + /* binderfs stashes devices in i_private */ + if (is_binderfs_device(nodp)) { + binder_dev = nodp->i_private; + info = nodp->i_sb->s_fs_info; + binder_binderfs_dir_entry_proc = info->proc_log_dir; + } else { + . + . + . + proc->context = &binder_dev->context; + +Now let's assume that the binderfs instance for that binder devices is +shutdown via umount() and/or the mount namespace associated with it goes +away. As long as there is still an fd open for that binderfs binder +device things are fine. But let's assume we now close the last fd for +that binderfs binder device. Now binder_release() is called and punts to +the workqueue. Assume that the workqueue has quite a bit of stuff to do +and doesn't get to cleaning up the struct binder_proc and the associated +struct binder_context with it for that binderfs binder device right +away. In the meantime, the VFS is killing the super block and is +ultimately calling sb->evict_inode() which means it will call +binderfs_evict_inode() which does: + +static void binderfs_evict_inode(struct inode *inode) +{ + struct binder_device *device = inode->i_private; + struct binderfs_info *info = BINDERFS_I(inode); + + clear_inode(inode); + + if (!S_ISCHR(inode->i_mode) || !device) + return; + + mutex_lock(&binderfs_minors_mutex); + --info->device_count; + ida_free(&binderfs_minors, device->miscdev.minor); + mutex_unlock(&binderfs_minors_mutex); + + kfree(device->context.name); + kfree(device); +} + +thereby freeing the struct binder_device including struct +binder_context. + +Now the workqueue finally has time to get around to cleaning up struct +binder_proc and is now trying to access the associate struct +binder_context. Since it's already freed it will OOPs. + +Fix this by holding an additional reference to the inode that is only +released once the workqueue is done cleaning up struct binder_proc. This +is an easy alternative to introducing separate refcounting on struct +binder_device which we can always do later if it becomes necessary. + +This is an alternative fix to 51d8a7eca677 ("binder: prevent UAF read in +print_binder_transaction_log_entry()"). + +Fixes: 3ad20fe393b3 ("binder: implement binderfs") +Fixes: 03e2e07e3814 ("binder: Make transaction_log available in binderfs") +Related : 51d8a7eca677 ("binder: prevent UAF read in print_binder_transaction_log_entry()") +Cc: stable@vger.kernel.org +Signed-off-by: Christian Brauner +Acked-by: Todd Kjos +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/android/binder.c | 5 ++++- + drivers/android/binder_internal.h | 13 +++++++++++++ + 2 files changed, 17 insertions(+), 1 deletion(-) + +--- a/drivers/android/binder.c ++++ b/drivers/android/binder.c +@@ -5219,7 +5219,7 @@ static int binder_open(struct inode *nod + proc->default_priority = task_nice(current); + /* binderfs stashes devices in i_private */ + if (is_binderfs_device(nodp)) { +- binder_dev = nodp->i_private; ++ binder_dev = binderfs_device_get(nodp->i_private); + info = nodp->i_sb->s_fs_info; + binder_binderfs_dir_entry_proc = info->proc_log_dir; + } else { +@@ -5403,6 +5403,7 @@ static int binder_node_release(struct bi + static void binder_deferred_release(struct binder_proc *proc) + { + struct binder_context *context = proc->context; ++ struct binder_device *device; + struct rb_node *n; + int threads, nodes, incoming_refs, outgoing_refs, active_transactions; + +@@ -5482,6 +5483,8 @@ static void binder_deferred_release(stru + outgoing_refs, active_transactions); + + binder_proc_dec_tmpref(proc); ++ device = container_of(proc->context, struct binder_device, context); ++ binderfs_device_put(device); + } + + static void binder_deferred_func(struct work_struct *work) +--- a/drivers/android/binder_internal.h ++++ b/drivers/android/binder_internal.h +@@ -35,6 +35,19 @@ struct binder_device { + struct inode *binderfs_inode; + }; + ++static inline struct binder_device *binderfs_device_get(struct binder_device *dev) ++{ ++ if (dev->binderfs_inode) ++ ihold(dev->binderfs_inode); ++ return dev; ++} ++ ++static inline void binderfs_device_put(struct binder_device *dev) ++{ ++ if (dev->binderfs_inode) ++ iput(dev->binderfs_inode); ++} ++ + /** + * binderfs_mount_opts - mount options for binderfs + * @max: maximum number of allocatable binderfs binder devices diff --git a/queue-5.5/cifs-don-t-leak-eagain-for-stat-during-reconnect.patch b/queue-5.5/cifs-don-t-leak-eagain-for-stat-during-reconnect.patch new file mode 100644 index 00000000000..99b778d0dcc --- /dev/null +++ b/queue-5.5/cifs-don-t-leak-eagain-for-stat-during-reconnect.patch @@ -0,0 +1,61 @@ +From fc513fac56e1b626ae48a74d7551d9c35c50129e Mon Sep 17 00:00:00 2001 +From: Ronnie Sahlberg +Date: Wed, 19 Feb 2020 06:01:03 +1000 +Subject: cifs: don't leak -EAGAIN for stat() during reconnect + +From: Ronnie Sahlberg + +commit fc513fac56e1b626ae48a74d7551d9c35c50129e upstream. + +If from cifs_revalidate_dentry_attr() the SMB2/QUERY_INFO call fails with an +error, such as STATUS_SESSION_EXPIRED, causing the session to be reconnected +it is possible we will leak -EAGAIN back to the application even for +system calls such as stat() where this is not a valid error. + +Fix this by re-trying the operation from within cifs_revalidate_dentry_attr() +if cifs_get_inode_info*() returns -EAGAIN. + +This fixes stat() and possibly also other system calls that uses +cifs_revalidate_dentry*(). + +Signed-off-by: Ronnie Sahlberg +Signed-off-by: Steve French +Reviewed-by: Pavel Shilovsky +Reviewed-by: Aurelien Aptel +CC: Stable +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/inode.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -2074,6 +2074,7 @@ int cifs_revalidate_dentry_attr(struct d + struct inode *inode = d_inode(dentry); + struct super_block *sb = dentry->d_sb; + char *full_path = NULL; ++ int count = 0; + + if (inode == NULL) + return -ENOENT; +@@ -2095,15 +2096,18 @@ int cifs_revalidate_dentry_attr(struct d + full_path, inode, inode->i_count.counter, + dentry, cifs_get_time(dentry), jiffies); + ++again: + if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext) + rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); + else + rc = cifs_get_inode_info(&inode, full_path, NULL, sb, + xid, NULL); +- ++ if (rc == -EAGAIN && count++ < 10) ++ goto again; + out: + kfree(full_path); + free_xid(xid); ++ + return rc; + } + diff --git a/queue-5.5/cifs-fix-rename-by-ensuring-source-handle-opened-with-delete-bit.patch b/queue-5.5/cifs-fix-rename-by-ensuring-source-handle-opened-with-delete-bit.patch new file mode 100644 index 00000000000..8ca2996dd4b --- /dev/null +++ b/queue-5.5/cifs-fix-rename-by-ensuring-source-handle-opened-with-delete-bit.patch @@ -0,0 +1,312 @@ +From 86f740f2aed5ea7fe1aa86dc2df0fb4ab0f71088 Mon Sep 17 00:00:00 2001 +From: Aurelien Aptel +Date: Fri, 21 Feb 2020 11:19:06 +0100 +Subject: cifs: fix rename() by ensuring source handle opened with DELETE bit + +From: Aurelien Aptel + +commit 86f740f2aed5ea7fe1aa86dc2df0fb4ab0f71088 upstream. + +To rename a file in SMB2 we open it with the DELETE access and do a +special SetInfo on it. If the handle is missing the DELETE bit the +server will fail the SetInfo with STATUS_ACCESS_DENIED. + +We currently try to reuse any existing opened handle we have with +cifs_get_writable_path(). That function looks for handles with WRITE +access but doesn't check for DELETE, making rename() fail if it finds +a handle to reuse. Simple reproducer below. + +To select handles with the DELETE bit, this patch adds a flag argument +to cifs_get_writable_path() and find_writable_file() and the existing +'bool fsuid_only' argument is converted to a flag. + +The cifsFileInfo struct only stores the UNIX open mode but not the +original SMB access flags. Since the DELETE bit is not mapped in that +mode, this patch stores the access mask in cifs_fid on file open, +which is accessible from cifsFileInfo. + +Simple reproducer: + + #include + #include + #include + #include + #include + #include + #define E(s) perror(s), exit(1) + + int main(int argc, char *argv[]) + { + int fd, ret; + if (argc != 3) { + fprintf(stderr, "Usage: %s A B\n" + "create&open A in write mode, " + "rename A to B, close A\n", argv[0]); + return 0; + } + + fd = openat(AT_FDCWD, argv[1], O_WRONLY|O_CREAT|O_SYNC, 0666); + if (fd == -1) E("openat()"); + + ret = rename(argv[1], argv[2]); + if (ret) E("rename()"); + + ret = close(fd); + if (ret) E("close()"); + + return ret; + } + +$ gcc -o bugrename bugrename.c +$ ./bugrename /mnt/a /mnt/b +rename(): Permission denied + +Fixes: 8de9e86c67ba ("cifs: create a helper to find a writeable handle by path name") +CC: Stable +Signed-off-by: Aurelien Aptel +Signed-off-by: Steve French +Reviewed-by: Pavel Shilovsky +Reviewed-by: Paulo Alcantara (SUSE) +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/cifsglob.h | 7 +++++++ + fs/cifs/cifsproto.h | 5 +++-- + fs/cifs/cifssmb.c | 3 ++- + fs/cifs/file.c | 19 ++++++++++++------- + fs/cifs/inode.c | 6 +++--- + fs/cifs/smb1ops.c | 2 +- + fs/cifs/smb2inode.c | 4 ++-- + fs/cifs/smb2ops.c | 3 ++- + fs/cifs/smb2pdu.c | 1 + + 9 files changed, 33 insertions(+), 17 deletions(-) + +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -1277,6 +1277,7 @@ struct cifs_fid { + __u64 volatile_fid; /* volatile file id for smb2 */ + __u8 lease_key[SMB2_LEASE_KEY_SIZE]; /* lease key for smb2 */ + __u8 create_guid[16]; ++ __u32 access; + struct cifs_pending_open *pending_open; + unsigned int epoch; + #ifdef CONFIG_CIFS_DEBUG2 +@@ -1737,6 +1738,12 @@ static inline bool is_retryable_error(in + return false; + } + ++ ++/* cifs_get_writable_file() flags */ ++#define FIND_WR_ANY 0 ++#define FIND_WR_FSUID_ONLY 1 ++#define FIND_WR_WITH_DELETE 2 ++ + #define MID_FREE 0 + #define MID_REQUEST_ALLOCATED 1 + #define MID_REQUEST_SUBMITTED 2 +--- a/fs/cifs/cifsproto.h ++++ b/fs/cifs/cifsproto.h +@@ -134,11 +134,12 @@ extern bool backup_cred(struct cifs_sb_i + extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof); + extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, + unsigned int bytes_written); +-extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool); ++extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, int); + extern int cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, +- bool fsuid_only, ++ int flags, + struct cifsFileInfo **ret_file); + extern int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name, ++ int flags, + struct cifsFileInfo **ret_file); + extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); + extern int cifs_get_readable_path(struct cifs_tcon *tcon, const char *name, +--- a/fs/cifs/cifssmb.c ++++ b/fs/cifs/cifssmb.c +@@ -1492,6 +1492,7 @@ openRetry: + *oplock = rsp->OplockLevel; + /* cifs fid stays in le */ + oparms->fid->netfid = rsp->Fid; ++ oparms->fid->access = desired_access; + + /* Let caller know file was created so we can set the mode. */ + /* Do we care about the CreateAction in any other cases? */ +@@ -2115,7 +2116,7 @@ cifs_writev_requeue(struct cifs_writedat + wdata2->tailsz = tailsz; + wdata2->bytes = cur_len; + +- rc = cifs_get_writable_file(CIFS_I(inode), false, ++ rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY, + &wdata2->cfile); + if (!wdata2->cfile) { + cifs_dbg(VFS, "No writable handle to retry writepages rc=%d\n", +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -1964,7 +1964,7 @@ struct cifsFileInfo *find_readable_file( + + /* Return -EBADF if no handle is found and general rc otherwise */ + int +-cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only, ++cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, int flags, + struct cifsFileInfo **ret_file) + { + struct cifsFileInfo *open_file, *inv_file = NULL; +@@ -1972,7 +1972,8 @@ cifs_get_writable_file(struct cifsInodeI + bool any_available = false; + int rc = -EBADF; + unsigned int refind = 0; +- ++ bool fsuid_only = flags & FIND_WR_FSUID_ONLY; ++ bool with_delete = flags & FIND_WR_WITH_DELETE; + *ret_file = NULL; + + /* +@@ -2004,6 +2005,8 @@ refind_writable: + continue; + if (fsuid_only && !uid_eq(open_file->uid, current_fsuid())) + continue; ++ if (with_delete && !(open_file->fid.access & DELETE)) ++ continue; + if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { + if (!open_file->invalidHandle) { + /* found a good writable file */ +@@ -2051,12 +2054,12 @@ refind_writable: + } + + struct cifsFileInfo * +-find_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only) ++find_writable_file(struct cifsInodeInfo *cifs_inode, int flags) + { + struct cifsFileInfo *cfile; + int rc; + +- rc = cifs_get_writable_file(cifs_inode, fsuid_only, &cfile); ++ rc = cifs_get_writable_file(cifs_inode, flags, &cfile); + if (rc) + cifs_dbg(FYI, "couldn't find writable handle rc=%d", rc); + +@@ -2065,6 +2068,7 @@ find_writable_file(struct cifsInodeInfo + + int + cifs_get_writable_path(struct cifs_tcon *tcon, const char *name, ++ int flags, + struct cifsFileInfo **ret_file) + { + struct list_head *tmp; +@@ -2091,7 +2095,7 @@ cifs_get_writable_path(struct cifs_tcon + kfree(full_path); + cinode = CIFS_I(d_inode(cfile->dentry)); + spin_unlock(&tcon->open_file_lock); +- return cifs_get_writable_file(cinode, 0, ret_file); ++ return cifs_get_writable_file(cinode, flags, ret_file); + } + + spin_unlock(&tcon->open_file_lock); +@@ -2168,7 +2172,8 @@ static int cifs_partialpagewrite(struct + if (mapping->host->i_size - offset < (loff_t)to) + to = (unsigned)(mapping->host->i_size - offset); + +- rc = cifs_get_writable_file(CIFS_I(mapping->host), false, &open_file); ++ rc = cifs_get_writable_file(CIFS_I(mapping->host), FIND_WR_ANY, ++ &open_file); + if (!rc) { + bytes_written = cifs_write(open_file, open_file->pid, + write_data, to - from, &offset); +@@ -2361,7 +2366,7 @@ retry: + if (cfile) + cifsFileInfo_put(cfile); + +- rc = cifs_get_writable_file(CIFS_I(inode), false, &cfile); ++ rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY, &cfile); + + /* in case of an error store it to return later */ + if (rc) +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -2283,7 +2283,7 @@ cifs_set_file_size(struct inode *inode, + * writebehind data than the SMB timeout for the SetPathInfo + * request would allow + */ +- open_file = find_writable_file(cifsInode, true); ++ open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY); + if (open_file) { + tcon = tlink_tcon(open_file->tlink); + server = tcon->ses->server; +@@ -2433,7 +2433,7 @@ cifs_setattr_unix(struct dentry *direntr + args->ctime = NO_CHANGE_64; + + args->device = 0; +- open_file = find_writable_file(cifsInode, true); ++ open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY); + if (open_file) { + u16 nfid = open_file->fid.netfid; + u32 npid = open_file->pid; +@@ -2536,7 +2536,7 @@ cifs_setattr_nounix(struct dentry *diren + rc = 0; + + if (attrs->ia_valid & ATTR_MTIME) { +- rc = cifs_get_writable_file(cifsInode, false, &wfile); ++ rc = cifs_get_writable_file(cifsInode, FIND_WR_ANY, &wfile); + if (!rc) { + tcon = tlink_tcon(wfile->tlink); + rc = tcon->ses->server->ops->flush(xid, tcon, &wfile->fid); +--- a/fs/cifs/smb1ops.c ++++ b/fs/cifs/smb1ops.c +@@ -765,7 +765,7 @@ smb_set_file_info(struct inode *inode, c + struct cifs_tcon *tcon; + + /* if the file is already open for write, just use that fileid */ +- open_file = find_writable_file(cinode, true); ++ open_file = find_writable_file(cinode, FIND_WR_FSUID_ONLY); + if (open_file) { + fid.netfid = open_file->fid.netfid; + netpid = open_file->pid; +--- a/fs/cifs/smb2inode.c ++++ b/fs/cifs/smb2inode.c +@@ -526,7 +526,7 @@ smb2_mkdir_setinfo(struct inode *inode, + cifs_i = CIFS_I(inode); + dosattrs = cifs_i->cifsAttrs | ATTR_READONLY; + data.Attributes = cpu_to_le32(dosattrs); +- cifs_get_writable_path(tcon, name, &cfile); ++ cifs_get_writable_path(tcon, name, FIND_WR_ANY, &cfile); + tmprc = smb2_compound_op(xid, tcon, cifs_sb, name, + FILE_WRITE_ATTRIBUTES, FILE_CREATE, + CREATE_NOT_FILE, ACL_NO_MODE, +@@ -582,7 +582,7 @@ smb2_rename_path(const unsigned int xid, + { + struct cifsFileInfo *cfile; + +- cifs_get_writable_path(tcon, from_name, &cfile); ++ cifs_get_writable_path(tcon, from_name, FIND_WR_WITH_DELETE, &cfile); + + return smb2_set_path_attr(xid, tcon, from_name, to_name, + cifs_sb, DELETE, SMB2_OP_RENAME, cfile); +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -1366,6 +1366,7 @@ smb2_set_fid(struct cifsFileInfo *cfile, + + cfile->fid.persistent_fid = fid->persistent_fid; + cfile->fid.volatile_fid = fid->volatile_fid; ++ cfile->fid.access = fid->access; + #ifdef CONFIG_CIFS_DEBUG2 + cfile->fid.mid = fid->mid; + #endif /* CIFS_DEBUG2 */ +@@ -3225,7 +3226,7 @@ static loff_t smb3_llseek(struct file *f + * some servers (Windows2016) will not reflect recent writes in + * QUERY_ALLOCATED_RANGES until SMB2_flush is called. + */ +- wrcfile = find_writable_file(cifsi, false); ++ wrcfile = find_writable_file(cifsi, FIND_WR_ANY); + if (wrcfile) { + filemap_write_and_wait(inode->i_mapping); + smb2_flush_file(xid, tcon, &wrcfile->fid); +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -2749,6 +2749,7 @@ SMB2_open(const unsigned int xid, struct + atomic_inc(&tcon->num_remote_opens); + oparms->fid->persistent_fid = rsp->PersistentFileId; + oparms->fid->volatile_fid = rsp->VolatileFileId; ++ oparms->fid->access = oparms->desired_access; + #ifdef CONFIG_CIFS_DEBUG2 + oparms->fid->mid = le64_to_cpu(rsp->sync_hdr.MessageId); + #endif /* CIFS_DEBUG2 */ diff --git a/queue-5.5/driver-core-call-sync_state-even-if-supplier-has-no-consumers.patch b/queue-5.5/driver-core-call-sync_state-even-if-supplier-has-no-consumers.patch new file mode 100644 index 00000000000..dace13da5d8 --- /dev/null +++ b/queue-5.5/driver-core-call-sync_state-even-if-supplier-has-no-consumers.patch @@ -0,0 +1,94 @@ +From 21eb93f432b1a785df193df1a56a59e9eb3a985f Mon Sep 17 00:00:00 2001 +From: Saravana Kannan +Date: Fri, 21 Feb 2020 00:05:08 -0800 +Subject: driver core: Call sync_state() even if supplier has no consumers + +From: Saravana Kannan + +commit 21eb93f432b1a785df193df1a56a59e9eb3a985f upstream. + +The initial patch that added sync_state() support didn't handle the case +where a supplier has no consumers. This was because when a device is +successfully bound with a driver, only its suppliers were checked to see +if they are eligible to get a sync_state(). This is not sufficient for +devices that have no consumers but still need to do device state clean +up. So fix this. + +Fixes: fc5a251d0fd7ca90 (driver core: Add sync_state driver/bus callback) +Signed-off-by: Saravana Kannan +Cc: stable +Link: https://lore.kernel.org/r/20200221080510.197337-2-saravanak@google.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/base/core.c | 23 +++++++++++++++++------ + 1 file changed, 17 insertions(+), 6 deletions(-) + +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -745,25 +745,31 @@ static void __device_links_queue_sync_st + /** + * device_links_flush_sync_list - Call sync_state() on a list of devices + * @list: List of devices to call sync_state() on ++ * @dont_lock_dev: Device for which lock is already held by the caller + * + * Calls sync_state() on all the devices that have been queued for it. This +- * function is used in conjunction with __device_links_queue_sync_state(). ++ * function is used in conjunction with __device_links_queue_sync_state(). The ++ * @dont_lock_dev parameter is useful when this function is called from a ++ * context where a device lock is already held. + */ +-static void device_links_flush_sync_list(struct list_head *list) ++static void device_links_flush_sync_list(struct list_head *list, ++ struct device *dont_lock_dev) + { + struct device *dev, *tmp; + + list_for_each_entry_safe(dev, tmp, list, links.defer_sync) { + list_del_init(&dev->links.defer_sync); + +- device_lock(dev); ++ if (dev != dont_lock_dev) ++ device_lock(dev); + + if (dev->bus->sync_state) + dev->bus->sync_state(dev); + else if (dev->driver && dev->driver->sync_state) + dev->driver->sync_state(dev); + +- device_unlock(dev); ++ if (dev != dont_lock_dev) ++ device_unlock(dev); + + put_device(dev); + } +@@ -801,7 +807,7 @@ void device_links_supplier_sync_state_re + out: + device_links_write_unlock(); + +- device_links_flush_sync_list(&sync_list); ++ device_links_flush_sync_list(&sync_list, NULL); + } + + static int sync_state_resume_initcall(void) +@@ -865,6 +871,11 @@ void device_links_driver_bound(struct de + driver_deferred_probe_add(link->consumer); + } + ++ if (defer_sync_state_count) ++ __device_links_supplier_defer_sync(dev); ++ else ++ __device_links_queue_sync_state(dev, &sync_list); ++ + list_for_each_entry(link, &dev->links.suppliers, c_node) { + if (!(link->flags & DL_FLAG_MANAGED)) + continue; +@@ -883,7 +894,7 @@ void device_links_driver_bound(struct de + + device_links_write_unlock(); + +- device_links_flush_sync_list(&sync_list); ++ device_links_flush_sync_list(&sync_list, dev); + } + + static void device_link_drop_managed(struct device_link *link) diff --git a/queue-5.5/firmware-imx-scu-ensure-sequential-tx.patch b/queue-5.5/firmware-imx-scu-ensure-sequential-tx.patch new file mode 100644 index 00000000000..957ea4d160d --- /dev/null +++ b/queue-5.5/firmware-imx-scu-ensure-sequential-tx.patch @@ -0,0 +1,85 @@ +From 26d0fba29c96241de8a9d16f045b1de49875884c Mon Sep 17 00:00:00 2001 +From: Leonard Crestez +Date: Thu, 20 Feb 2020 18:10:01 +0200 +Subject: firmware: imx: scu: Ensure sequential TX + +From: Leonard Crestez + +commit 26d0fba29c96241de8a9d16f045b1de49875884c upstream. + +SCU requires that all messages words are written sequentially but linux MU +driver implements multiple independent channels for each register so ordering +between different channels must be ensured by SCU API interface. + +Wait for tx_done before every send to ensure that no queueing happens at the +mailbox channel level. + +Fixes: edbee095fafb ("firmware: imx: add SCU firmware driver support") +Signed-off-by: Leonard Crestez +Cc: +Reviewed-by: Peng Fan +Reviewed-by:: Oleksij Rempel +Signed-off-by: Shawn Guo +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/firmware/imx/imx-scu.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +--- a/drivers/firmware/imx/imx-scu.c ++++ b/drivers/firmware/imx/imx-scu.c +@@ -29,6 +29,7 @@ struct imx_sc_chan { + struct mbox_client cl; + struct mbox_chan *ch; + int idx; ++ struct completion tx_done; + }; + + struct imx_sc_ipc { +@@ -100,6 +101,14 @@ int imx_scu_get_handle(struct imx_sc_ipc + } + EXPORT_SYMBOL(imx_scu_get_handle); + ++/* Callback called when the word of a message is ack-ed, eg read by SCU */ ++static void imx_scu_tx_done(struct mbox_client *cl, void *mssg, int r) ++{ ++ struct imx_sc_chan *sc_chan = container_of(cl, struct imx_sc_chan, cl); ++ ++ complete(&sc_chan->tx_done); ++} ++ + static void imx_scu_rx_callback(struct mbox_client *c, void *msg) + { + struct imx_sc_chan *sc_chan = container_of(c, struct imx_sc_chan, cl); +@@ -149,6 +158,19 @@ static int imx_scu_ipc_write(struct imx_ + + for (i = 0; i < hdr->size; i++) { + sc_chan = &sc_ipc->chans[i % 4]; ++ ++ /* ++ * SCU requires that all messages words are written ++ * sequentially but linux MU driver implements multiple ++ * independent channels for each register so ordering between ++ * different channels must be ensured by SCU API interface. ++ * ++ * Wait for tx_done before every send to ensure that no ++ * queueing happens at the mailbox channel level. ++ */ ++ wait_for_completion(&sc_chan->tx_done); ++ reinit_completion(&sc_chan->tx_done); ++ + ret = mbox_send_message(sc_chan->ch, &data[i]); + if (ret < 0) + return ret; +@@ -247,6 +269,11 @@ static int imx_scu_probe(struct platform + cl->knows_txdone = true; + cl->rx_callback = imx_scu_rx_callback; + ++ /* Initial tx_done completion as "done" */ ++ cl->tx_done = imx_scu_tx_done; ++ init_completion(&sc_chan->tx_done); ++ complete(&sc_chan->tx_done); ++ + sc_chan->sc_ipc = sc_ipc; + sc_chan->idx = i % 4; + sc_chan->ch = mbox_request_channel_byname(cl, chan_name); diff --git a/queue-5.5/series b/queue-5.5/series index c521fbe6a77..22c88a62a38 100644 --- a/queue-5.5/series +++ b/queue-5.5/series @@ -55,3 +55,14 @@ csky-fixup-ftrace-modify-panic.patch csky-fixup-compile-warning-for-three-unimplemented-s.patch arch-csky-fix-some-kconfig-typos.patch selftests-forwarding-vxlan_bridge_1d-use-more-proper.patch +firmware-imx-scu-ensure-sequential-tx.patch +binder-prevent-uaf-for-binderfs-devices.patch +binder-prevent-uaf-for-binderfs-devices-ii.patch +alsa-hda-realtek-add-headset-mic-supported.patch +alsa-hda-realtek-add-headset-button-supported-for-thinkpad-x1.patch +alsa-hda-realtek-fix-a-regression-for-mute-led-on-lenovo-carbon-x1.patch +alsa-hda-realtek-fix-silent-output-on-gigabyte-x570-aorus-master.patch +alsa-hda-realtek-enable-the-headset-of-asus-b9450fa-with-alc294.patch +driver-core-call-sync_state-even-if-supplier-has-no-consumers.patch +cifs-don-t-leak-eagain-for-stat-during-reconnect.patch +cifs-fix-rename-by-ensuring-source-handle-opened-with-delete-bit.patch