5.11.7-rc1 review
Subsystems (4)
[email protected]
maintainerPATCH 145/306 sparc64: Use arch_validate_flags() to validate ADI flag
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Khalid Aziz <[email protected]>
[ Upstream commit 147d8622f2a26ef34beacc60e1ed8b66c2fa457f ]
When userspace calls mprotect() to enable ADI on an address range, do_mprotect_pkey() calls arch_validate_prot() to validate new protection flags. arch_validate_prot() for sparc looks at the first VMA associated with address range to verify if ADI can indeed be enabled on this address range. This has two issues - (1) Address range might cover multiple VMAs while arch_validate_prot() looks at only the first VMA, (2) arch_validate_prot() peeks at VMA without holding mmap lock which can result in race condition.
arch_validate_flags() from commit c462ac288f2c ("mm: Introduce arch_validate_flags()") allows for VMA flags to be validated for all VMAs that cover the address range given by user while holding mmap lock. This patch updates sparc code to move the VMA check from arch_validate_prot() to arch_validate_flags() to fix above two issues.
--- arch/sparc/include/asm/mman.h | 54 +++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 25 deletions(-)
arch/sparc/include/asm/mman.h +29 -25
@@ -57,35 +57,39 @@ static inline int sparc_validate_prot(unsigned long prot, unsigned long addr) {if (prot & ~(PROT_READ |PROT_WRITE |PROT_EXEC |PROT_SEM |PROT_ADI ))return 0 ; -if (prot &PROT_ADI ) { -if (!adi_capable ()) -return 0 ; +return 1 ; +} -if (addr) { -struct vm_area_struct *vma; +#define arch_validate_flags (vm_flags) arch_validate_flags(vm_flags) +/* arch_validate_flags() - Ensure combination of flags is valid for a +* VMA. +*/ +static inline bool arch_validate_flags (unsigned long vm_flags) +{ +/* If ADI is being enabled on this VMA, check for ADI +* capability on the platform and ensure VMA is suitable +* for ADI +*/ +if (vm_flags &VM_SPARC_ADI ) { +if (!adi_capable ()) +return false; - vma =find_vma (current->mm, addr); -if (vma) { -/* ADI can not be enabled on PFN -* mapped pages -*/ -if (vma->vm_flags & (VM_PFNMAP |VM_MIXEDMAP )) -return 0 ; +/* ADI can not be enabled on PFN mapped pages */ +if (vm_flags & (VM_PFNMAP |VM_MIXEDMAP )) +return false; -/* Mergeable pages can become unmergeable -* if ADI is enabled on them even if they -* have identical data on them. This can be -* because ADI enabled pages with identical -* data may still not have identical ADI -* tags on them. Disallow ADI on mergeable -* pages. -*/ -if (vma->vm_flags &VM_MERGEABLE ) -return 0 ; - } - } +/* Mergeable pages can become unmergeable +* if ADI is enabled on them even if they +* have identical data on them. This can be +* because ADI enabled pages with identical +* data may still not have identical ADI +* tags on them. Disallow ADI on mergeable +* pages. +*/ +if (vm_flags &VM_MERGEABLE ) +return false; } -return 1 ; +return true; }#endif /* CONFIG_SPARC64 */
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 146/306 Input: applespi - dont wait for responses to commands indefinitely.
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Ronald Tschalär <[email protected]>
[ Upstream commit 0ce1ac23149c6da939a5926c098c270c58c317a0 ]
The response to a command may never arrive or it may be corrupted (and hence dropped) for some reason. While exceedingly rare, when it did happen it blocked all further commands. One way to fix this was to do a suspend/resume. However, recovering automatically seems like a nicer option. Hence this puts a time limit (1 sec) on how long we're willing to wait for a response, after which we assume it got lost.
--- drivers/input/keyboard/applespi.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-)
drivers/input/keyboard/applespi.c +15 -6
@@ -48,6 +48,7 @@#include <linux/efi.h> #include <linux/input.h> #include <linux/input/mt.h> +#include <linux/ktime.h> #include <linux/leds.h> #include <linux/module.h> #include <linux/spinlock.h>
@@ -409,7 +410,7 @@ struct applespi_data {unsigned int cmd_msg_cntr;/* lock to protect the above parameters and flags below */ spinlock_t cmd_msg_lock; -bool cmd_msg_queued; +ktime_t cmd_msg_queued;enum applespi_evt_type cmd_evt_type;struct led_classdev backlight_info;
@@ -729,7 +730,7 @@ static void applespi_msg_complete(struct applespi_data *applespi,wake_up_all (&applespi->drain_complete);if (is_write_msg) { - applespi->cmd_msg_queued = false; + applespi->cmd_msg_queued =0 ;applespi_send_cmd_msg (applespi); }
@@ -771,8 +772,16 @@ static int applespi_send_cmd_msg(struct applespi_data *applespi)return 0 ;/* check whether send is in progress */ -if (applespi->cmd_msg_queued) -return 0 ; +if (applespi->cmd_msg_queued) { +if (ktime_ms_delta (ktime_get (), applespi->cmd_msg_queued) <1000 ) +return 0 ; + +dev_warn (&applespi->spi->dev,"Command %d timed out\n" , + applespi->cmd_evt_type); + + applespi->cmd_msg_queued =0 ; + applespi->write_active = false; + }/* set up packet */ memset (packet,0 ,APPLESPI_PACKET_SIZE );
@@ -869,7 +878,7 @@ static int applespi_send_cmd_msg(struct applespi_data *applespi)return sts; } - applespi->cmd_msg_queued = true; + applespi->cmd_msg_queued =ktime_get_coarse (); applespi->write_active = true;return 0 ;
@@ -1921,7 +1930,7 @@ static int __maybe_unused applespi_resume(struct device *dev) applespi->drain = false; applespi->have_cl_led_on = false; applespi->have_bl_level =0 ; - applespi->cmd_msg_queued = false; + applespi->cmd_msg_queued =0 ; applespi->read_active = false; applespi->write_active = false;
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 147/306 PCI: xgene-msi: Fix race in installing chained irq handler
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Martin Kaiser <[email protected]>
[ Upstream commit a93c00e5f975f23592895b7e83f35de2d36b7633 ]
Fix a race where a pending interrupt could be received and the handler called before the handler's data has been setup, by converting to irq_set_chained_handler_and_data().
See also 2cf5a03cb29d ("PCI/keystone: Fix race in installing chained IRQ handler").
Based on the mail discussion, it seems ok to drop the error handling.
--- drivers/pci/controller/pci-xgene-msi.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-)
drivers/pci/controller/pci-xgene-msi.c +3 -7
@@ -384,13 +384,9 @@ static int xgene_msi_hwirq_alloc(unsigned int cpu)if (!msi_group->gic_irq)continue ; -irq_set_chained_handler (msi_group->gic_irq, - xgene_msi_isr); - err =irq_set_handler_data (msi_group->gic_irq, msi_group); -if (err) { -pr_err ("failed to register GIC IRQ handler\n" ); -return -EINVAL ; - } +irq_set_chained_handler_and_data (msi_group->gic_irq, + xgene_msi_isr, msi_group); +/* * Statically allocate MSI GIC IRQs to each CPU core. * With 8-core X-Gene v1, 2 MSI GIC IRQs are allocated
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 148/306 PCI: mediatek: Add missing of_node_put() to fix reference leak
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Krzysztof Wilczyński <[email protected]>
[ Upstream commit 42814c438aac79746d310f413a27d5b0b959c5de ]
The for_each_available_child_of_node helper internally makes use of the of_get_next_available_child() which performs an of_node_get() on each iteration when searching for next available child node.
Should an available child node be found, then it would return a device node pointer with reference count incremented, thus early return from the middle of the loop requires an explicit of_node_put() to prevent reference count leak.
To stop the reference leak, explicitly call of_node_put() before returning after an error occurred.
--- drivers/pci/controller/pcie-mediatek.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/pci/controller/pcie-mediatek.c +5 -2
@@ -1035,14 +1035,14 @@ static int mtk_pcie_setup(struct mtk_pcie *pcie) err =of_pci_get_devfn (child);if (err <0 ) {dev_err (dev,"failed to parse devfn: %d\n" , err); -return err; + goto error_put_node; } slot =PCI_SLOT (err); err =mtk_pcie_parse_port (pcie, child, slot);if (err) -return err; + goto error_put_node; } err =mtk_pcie_subsys_powerup (pcie);
@@ -1058,6 +1058,9 @@ static int mtk_pcie_setup(struct mtk_pcie *pcie)mtk_pcie_subsys_powerdown (pcie);return 0 ; +error_put_node: +of_node_put (child); +return err; }static int mtk_pcie_probe (struct platform_device *pdev)
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 149/306 drivers/base: build kunit tests without structleak plugin
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Arnd Bergmann <[email protected]>
[ Upstream commit 38009c766725a9877ea8866fc813a5460011817f ]
The structleak plugin causes the stack frame size to grow immensely:
drivers/base/test/property-entry-test.c: In function 'pe_test_reference':drivers/base/test/property-entry-test.c:481:1: error: the frame size of 2640 bytes is larger than 2048 bytes [-Werror=frame-larger-than=]
481 | }
| ^
drivers/base/test/property-entry-test.c: In function 'pe_test_uints':drivers/base/test/property-entry-test.c:99:1: error: the frame size of 2592 bytes is larger than 2048 bytes [-Werror=frame-larger-than=]
Turn it off in this file.
--- drivers/base/test/Makefile | 1 + 1 file changed, 1 insertion(+)
drivers/base/test/Makefile +1 -0
@@ -2,3 +2,4 @@ obj-$(CONFIG_TEST_ASYNC_DRIVER_PROBE) += test_async_driver_probe.o obj-$(CONFIG_KUNIT_DRIVER_PE_TEST) += property-entry-test.o +CFLAGS_REMOVE_property-entry-test.o += -fplugin-arg-structleak_plugin-byref -fplugin-arg-structleak_plugin-byref-all
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 150/306 PCI/LINK: Remove bandwidth notification
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Bjorn Helgaas <[email protected]>
[ Upstream commit b4c7d2076b4e767dd2e075a2b3a9e57753fc67f5 ]
The PCIe Bandwidth Change Notification feature logs messages when the link bandwidth changes. Some users have reported that these messages occur often enough to significantly reduce NVMe performance. GPUs also seem to generate these messages.
We don't know why the link bandwidth changes, but in the reported cases there's no indication that it's caused by hardware failures.
Remove the bandwidth change notifications for now. Hopefully we can add this back when we have a better understanding of why this happens and how we can make the messages useful instead of overwhelming.
--- drivers/pci/pcie/Kconfig | 8 -- drivers/pci/pcie/Makefile | 1 - drivers/pci/pcie/bw_notification.c | 138 ----------------------------- drivers/pci/pcie/portdrv.h | 6 -- drivers/pci/pcie/portdrv_pci.c | 1 - 5 files changed, 154 deletions(-) delete mode 100644 drivers/pci/pcie/bw_notification.c
drivers/pci/pcie/Kconfig +0 -8
@@ -133,14 +133,6 @@ config PCIE_PTM This is only useful if you have devices that support PTM, but it is safe to enable even if you don't. -config PCIE_BW - bool "PCI Express Bandwidth Change Notification" - depends on PCIEPORTBUS - help - This enables PCI Express Bandwidth Change Notification. If - you know link width or rate changes occur only to correct - unreliable links, you may answer Y. - config PCIE_EDR bool "PCI Express Error Disconnect Recover support" depends on PCIE_DPC && ACPI
drivers/pci/pcie/Makefile +0 -1
@@ -12,5 +12,4 @@ obj-$(CONFIG_PCIEAER_INJECT) += aer_inject.o obj-$(CONFIG_PCIE_PME) += pme.o obj-$(CONFIG_PCIE_DPC) += dpc.o obj-$(CONFIG_PCIE_PTM) += ptm.o -obj-$(CONFIG_PCIE_BW) += bw_notification.o obj-$(CONFIG_PCIE_EDR) += edr.o
drivers/pci/pcie/bw_notification.c deleted +0 -138
138 lines not on this page · raw message
drivers/pci/pcie/portdrv.h +0 -6
@@ -53,12 +53,6 @@ int pcie_dpc_init(void);static inline int pcie_dpc_init (void ) {return 0 ; }#endif -#ifdef CONFIG_PCIE_BW -int pcie_bandwidth_notification_init (void ); -#else -static inline int pcie_bandwidth_notification_init (void ) {return 0 ; } -#endif -/* Port Type */ #define PCIE_ANY_PORT (~0)
drivers/pci/pcie/portdrv_pci.c +0 -1
@@ -255,7 +255,6 @@ static void __init pcie_init_services(void)pcie_pme_init ();pcie_dpc_init ();pcie_hp_init (); -pcie_bandwidth_notification_init (); }static int __init pcie_portdrv_init (void )
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 151/306 ext4: dont try to processed freed blocks until mballoc is initialized
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Theodore Ts'o <[email protected]>
[ Upstream commit 027f14f5357279655c3ebc6d14daff8368d4f53f ]
If we try to make any changes via the journal between when the journal is initialized, but before the multi-block allocated is initialized, we will end up deferencing a NULL pointer when the journal commit callback function calls ext4_process_freed_data().
The proximate cause of this failure was commit 2d01ddc86606 ("ext4:
save error info to sb through journal if available") since file system corruption problems detected before the call to ext4_mb_init() would result in a journal commit before we aborted the mount of the file system.... and we would then trigger the NULL pointer deref.
--- fs/ext4/super.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
fs/ext4/super.c +8 -1
@@ -4875,7 +4875,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)set_task_ioprio (sbi->s_journal->j_task, journal_ioprio); - sbi->s_journal->j_commit_callback = ext4_journal_commit_callback; sbi->s_journal->j_submit_inode_data_buffers = ext4_journal_submit_inode_data_buffers; sbi->s_journal->j_finish_inode_data_buffers =
@@ -4987,6 +4986,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) goto failed_mount5; } +/* +* We can only set up the journal commit callback once +* mballoc is initialized +*/ +if (sbi->s_journal) + sbi->s_journal->j_commit_callback = + ext4_journal_commit_callback; + block =ext4_count_free_clusters (sb);ext4_free_blocks_count_set (sbi->s_es,EXT4_C2B (sbi, block));
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 152/306 kbuild: clamp SUBLEVEL to 255
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
[ Upstream commit 9b82f13e7ef316cdc0a8858f1349f4defce3f9e0 ]
Right now if SUBLEVEL becomes larger than 255 it will overflow into the territory of PATCHLEVEL, causing havoc in userspace that tests for specific kernel version.
While userspace code tests for MAJOR and PATCHLEVEL, it doesn't test SUBLEVEL at any point as ABI changes don't happen in the context of stable tree.
Thus, to avoid overflows, simply clamp SUBLEVEL to it's maximum value in the context of LINUX_VERSION_CODE. This does not affect "make kernelversion" and such.
--- Makefile | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
Makefile +9 -3
@@ -1246,9 +1246,15 @@ define filechk_utsrelease.h endef define filechk_version.h - echo \#define LINUX_VERSION_CODE $(shell \ - expr $(VERSION) \* 65536 + 0$(PATCHLEVEL) \* 256 + 0$(SUBLEVEL)); \ - echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))' + if [ $(SUBLEVEL) -gt 255 ]; then \ + echo \#define LINUX_VERSION_CODE $(shell \ + expr $(VERSION) \* 65536 + 0$(PATCHLEVEL) \* 256 + 255); \ + else \ + echo \#define LINUX_VERSION_CODE $(shell \ + expr $(VERSION) \* 65536 + 0$(PATCHLEVEL) \* 256 + $(SUBLEVEL)); \ + fi; \ + echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + \ + ((c) > 255 ? 255 : (c)))' endef $(version_h): FORCE
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 153/306 PCI: Fix pci_register_io_range() memory leak
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Geert Uytterhoeven <[email protected]>
[ Upstream commit f6bda644fa3a7070621c3bf12cd657f69a42f170 ]
Kmemleak reports:
unreferenced object 0xc328de40 (size 64):
comm "kworker/1:1", pid 21, jiffies 4294938212 (age 1484.670s)
hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 e0 d8 fc eb 00 00 00 00 ................
00 00 10 fe 00 00 00 00 00 00 00 00 00 00 00 00 ................backtrace:
[<ad758d10>] pci_register_io_range+0x3c/0x80
[<2c7f139e>] of_pci_range_to_resource+0x48/0xc0
[<f079ecc8>] devm_of_pci_get_host_bridge_resources.constprop.0+0x2ac/0x3ac
[<e999753b>] devm_of_pci_bridge_init+0x60/0x1b8
[<a895b229>] devm_pci_alloc_host_bridge+0x54/0x64
[<e451ddb0>] rcar_pcie_probe+0x2c/0x644In case a PCI host driver's probe is deferred, the same I/O range may be allocated again, and be ignored, causing a memory leak.
Fix this by (a) letting logic_pio_register_range() return -EEXIST if the passed range already exists, so pci_register_io_range() will free it, and by (b) making pci_register_io_range() not consider -EEXIST an error condition.
--- drivers/pci/pci.c | 4 ++++ lib/logic_pio.c | 3 +++ 2 files changed, 7 insertions(+)
drivers/pci/pci.c +4 -0
@@ -4029,6 +4029,10 @@ int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr, ret =logic_pio_register_range (range);if (ret)kfree (range); + +/* Ignore duplicates due to deferred probing */ +if (ret == -EEXIST ) + ret =0 ;#endif return ret;
lib/logic_pio.c +3 -0
@@ -28,6 +28,8 @@ static DEFINE_MUTEX(io_range_mutex);* @new_range: pointer to the IO range to be registered. * * Returns 0 on success, the error code in case of failure. +* If the range already exists, -EEXIST will be returned, which should be +* considered a success. * * Register a new IO range node in the IO range list. */
@@ -51,6 +53,7 @@ int logic_pio_register_range(struct logic_pio_hwaddr *new_range)list_for_each_entry (range, &io_range_list, list) {if (range->fwnode == new_range->fwnode) {/* range already there */ + ret = -EEXIST ; goto end_register; } if (range->flags == LOGIC_PIO_CPU_MMIO &&
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 154/306 i40e: Fix memory leak in i40e_probe
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Keita Suzuki <[email protected]>
[ Upstream commit 58cab46c622d6324e47bd1c533693c94498e4172 ]
Struct i40e_veb is allocated in function i40e_setup_pf_switch, and stored to an array field veb inside struct i40e_pf. However when i40e_setup_misc_vector fails, this memory leaks.
Fix this by calling exit and teardown functions.
--- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/ethernet/intel/i40e/i40e_main.c +2 -0
@@ -15100,6 +15100,8 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)if (err) {dev_info (&pdev->dev,"setup of misc vector failed: %d\n" , err); +i40e_cloud_filter_exit (pf); +i40e_fdir_teardown (pf); goto err_vsis; } }
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 155/306 PCI/ERR: Retain status from error notification
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Keith Busch <[email protected]>
[ Upstream commit 387c72cdd7fb6bef650fb078d0f6ae9682abf631 ]
Overwriting the frozen detected status with the result of the link reset loses the NEED_RESET result that drivers are depending on for error handling to report the .slot_reset() callback. Retain this status so that subsequent error handling has the correct flow.
--- drivers/pci/pcie/err.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/pci/pcie/err.c +1 -2
@@ -198,8 +198,7 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,pci_dbg (bridge,"broadcast error_detected message\n" );if (state == pci_channel_io_frozen) {pci_walk_bridge (bridge, report_frozen_detected, &status); - status =reset_subordinates (bridge); -if (status !=PCI_ERS_RESULT_RECOVERED ) { +if (reset_subordinates (bridge) !=PCI_ERS_RESULT_RECOVERED ) {pci_warn (bridge,"subordinate device reset failed\n" ); goto failed; }
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 156/306 kasan: fix memory corruption in kasan_bitops_tags test
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Andrey Konovalov <[email protected]>
[ Upstream commit e66e1799a76621003e5b04c9c057826a2152e103 ]
Since the hardware tag-based KASAN mode might not have a redzone that comes after an allocated object (when kasan.mode=prod is enabled), the kasan_bitops_tags() test ends up corrupting the next object in memory.
Change the test so it always accesses the redzone that lies within the allocated object's boundaries.
--- lib/test_kasan.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
lib/test_kasan.c +5 -5
@@ -737,13 +737,13 @@ static void kasan_bitops_tags(struct kunit *test)return ; } -/* Allocation size will be rounded to up granule size, which is 16. */ - bits =kzalloc (sizeof (*bits),GFP_KERNEL ); +/* kmalloc-64 cache will be used and the last 16 bytes will be the redzone. */ + bits =kzalloc (48 ,GFP_KERNEL );KUNIT_ASSERT_NOT_ERR_OR_NULL (test, bits); -/* Do the accesses past the 16 allocated bytes. */ -kasan_bitops_modify (test,BITS_PER_LONG , &bits[1 ]); -kasan_bitops_test_and_modify (test,BITS_PER_LONG +BITS_PER_BYTE , &bits[1 ]); +/* Do the accesses past the 48 allocated bytes, but within the redone. */ +kasan_bitops_modify (test,BITS_PER_LONG , (void *)bits +48 ); +kasan_bitops_test_and_modify (test,BITS_PER_LONG +BITS_PER_BYTE , (void *)bits +48 );kfree (bits); }
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 157/306 s390/smp: __smp_rescan_cpus() - move cpumask away from stack
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Heiko Carstens <[email protected]>
[ Upstream commit 62c8dca9e194326802b43c60763f856d782b225c ]
Avoid a potentially large stack frame and overflow by making "cpumask_t avail" a static variable. There is no concurrent access due to the existing locking.
--- arch/s390/kernel/smp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/s390/kernel/smp.c +1 -1
@@ -770,7 +770,7 @@ static int smp_add_core(struct sclp_core_entry *core, cpumask_t *avail,static int __smp_rescan_cpus (struct sclp_core_info *info,bool early) {struct sclp_core_entry *core; -cpumask_t avail; +static cpumask_t avail;bool configured;u16 core_id;int nr, i;
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 158/306 drivers/base/memory: dont store phys_device in memory blocks
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: David Hildenbrand <[email protected]>
[ Upstream commit e9a2e48e8704c9d20a625c6f2357147d03ea7b97 ]
No need to store the value for each and every memory block, as we can easily query the value at runtime. Reshuffle the members to optimize the memory layout. Also, let's clarify what the interface once was used for and why it's legacy nowadays.
"phys_device" was used on s390x in older versions of lsmem[2]/chmem[3], back when they were still part of s390x-tools. They were later replaced by the variants in linux-utils. For example, RHEL6 and RHEL7 contain lsmem/chmem from s390-utils. RHEL8 switched to versions from util-linux on s390x [4].
"phys_device" was added with sysfs support for memory hotplug in commit 3947be1969a9 ("[PATCH] memory hotplug: sysfs and add/remove functions") in 2005. It always returned 0.
s390x started returning something != 0 on some setups (if sclp.rzm is set by HW) in 2010 via commit 57b552ba0b2f ("memory hotplug/s390: set phys_device").
For s390x, it allowed for identifying which memory block devices belong to the same storage increment (RZM). Only if all memory block devices comprising a single storage increment were offline, the memory could actually be removed in the hypervisor.
Since commit e5d709bb5fb7 ("s390/memory hotplug: provide memory_block_size_bytes() function") in 2013 a memory block device spans at least one storage increment - which is why the interface isn't really helpful/used anymore (except by old lsmem/chmem tools).
There were once RFC patches to make use of "phys_device" in ACPI context; however, the underlying problem could be solved using different interfaces [1].
[1] https://patchwork.kernel.org/patch/2163871/
[2] https://github.com/ibm-s390-tools/s390-tools/blob/v2.1.0/zconf/lsmem
[3] https://github.com/ibm-s390-tools/s390-tools/blob/v2.1.0/zconf/chmem
[4] https://bugzilla.redhat.com/show_bug.cgi?id=1504134
--- .../ABI/testing/sysfs-devices-memory | 5 ++-- .../admin-guide/mm/memory-hotplug.rst | 4 +-- drivers/base/memory.c | 25 +++++++------------ include/linux/memory.h | 3 +-- 4 files changed, 15 insertions(+), 22 deletions(-)
Documentation/ABI/testing/sysfs-devices-memory +3 -2
@@ -26,8 +26,9 @@ Date: September 2008 Contact: Badari Pulavarty <[email protected]> Description: The file /sys/devices/system/memory/memoryX/phys_device - is read-only and is designed to show the name of physical - memory device. Implementation is currently incomplete. + is read-only; it is a legacy interface only ever used on s390x + to expose the covered storage increment. +Users: Legacy s390-tools lsmem/chmem What: /sys/devices/system/memory/memoryX/phys_index Date: September 2008
Documentation/admin-guide/mm/memory-hotplug.rst +2 -2
@@ -160,8 +160,8 @@ Under each memory block, you can see 5 files: "online_movable", "online", "offline" command which will be performed on all sections in the block. -``phys_device`` read-only: designed to show the name of physical memory - device. This is not well implemented now. +``phys_device`` read-only: legacy interface only ever used on s390x to + expose the covered storage increment. ``removable`` read-only: contains an integer value indicating whether the memory block is removable or not removable. A value of 1 indicates that the memory
drivers/base/memory.c +9 -16
@@ -290,20 +290,20 @@ static ssize_t state_store(struct device *dev, struct device_attribute *attr, }/* -* phys_device is a bad name for this. What I really want -* is a way to differentiate between memory ranges that -* are part of physical devices that constitute -* a complete removable unit or fru. -* i.e. do these ranges belong to the same physical device, -* s.t. if I offline all of these sections I can then -* remove the physical device? +* Legacy interface that we cannot remove: s390x exposes the storage increment +* covered by a memory block, allowing for identifying which memory blocks +* comprise a storage increment. Since a memory block spans complete +* storage increments nowadays, this interface is basically unused. Other +* archs never exposed != 0. */ static ssize_t phys_device_show (struct device *dev,struct device_attribute *attr,char *buf) {struct memory_block *mem =to_memory_block (dev); +unsigned long start_pfn =section_nr_to_pfn (mem->start_section_nr); -return sysfs_emit (buf,"%d\n" , mem->phys_device); +return sysfs_emit (buf,"%d\n" , +arch_get_memory_phys_device (start_pfn)); }#ifdef CONFIG_MEMORY_HOTREMOVE
@@ -488,11 +488,7 @@ static DEVICE_ATTR_WO(soft_offline_page);static DEVICE_ATTR_WO (hard_offline_page);#endif -/* -* Note that phys_device is optional. It is here to allow for -* differentiation between which *physical* devices each -* section belongs to... -*/ +/* See phys_device_show(). */ int __weak arch_get_memory_phys_device (unsigned long start_pfn) {return 0 ;
@@ -574,7 +570,6 @@ int register_memory(struct memory_block *memory)static int init_memory_block (unsigned long block_id,unsigned long state) {struct memory_block *mem; -unsigned long start_pfn;int ret =0 ; mem =find_memory_block_by_id (block_id);
@@ -588,8 +583,6 @@ static int init_memory_block(unsigned long block_id, unsigned long state) mem->start_section_nr = block_id * sections_per_block; mem->state = state; - start_pfn =section_nr_to_pfn (mem->start_section_nr); - mem->phys_device =arch_get_memory_phys_device (start_pfn); mem->nid =NUMA_NO_NODE ; ret =register_memory (mem);
include/linux/memory.h +1 -2
@@ -27,9 +27,8 @@ struct memory_block {unsigned long start_section_nr;unsigned long state;/* serialized by the dev->lock */ int online_type;/* for passing data to online routine */ -int phys_device;/* to which fru does this belong? */ -struct device dev;int nid;/* NID for this memory block */ +struct device dev; };int arch_get_memory_phys_device (unsigned long start_pfn);
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 159/306 sysctl.c: fix underflow value setting risk in vm_table
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Lin Feng <[email protected]>
[ Upstream commit 3b3376f222e3ab58367d9dd405cafd09d5e37b7c ]
Apart from subsystem specific .proc_handler handler, all ctl_tables with extra1 and extra2 members set should use proc_dointvec_minmax instead of proc_dointvec, or the limit set in extra* never work and potentially echo underflow values(negative numbers) is likely make system unstable.
Especially vfs_cache_pressure and zone_reclaim_mode, -1 is apparently not a valid value, but we can set to them. And then kernel may crash.
# echo -1 > /proc/sys/vm/vfs_cache_pressure
--- kernel/sysctl.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
kernel/sysctl.c +4 -4
@@ -2962,7 +2962,7 @@ static struct ctl_table vm_table[] = { .data = &block_dump, .maxlen = sizeof(block_dump), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = proc_dointvec_minmax, .extra1 = SYSCTL_ZERO, }, {
@@ -2970,7 +2970,7 @@ static struct ctl_table vm_table[] = { .data = &sysctl_vfs_cache_pressure, .maxlen = sizeof(sysctl_vfs_cache_pressure), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = proc_dointvec_minmax, .extra1 = SYSCTL_ZERO, }, #if defined(HAVE_ARCH_PICK_MMAP_LAYOUT) || \
@@ -2980,7 +2980,7 @@ static struct ctl_table vm_table[] = { .data = &sysctl_legacy_va_layout, .maxlen = sizeof(sysctl_legacy_va_layout), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = proc_dointvec_minmax, .extra1 = SYSCTL_ZERO, },#endif
@@ -2990,7 +2990,7 @@ static struct ctl_table vm_table[] = { .data = &node_reclaim_mode, .maxlen = sizeof(node_reclaim_mode), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = proc_dointvec_minmax, .extra1 = SYSCTL_ZERO, }, {
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 160/306 scsi: libiscsi: Fix iscsi_prep_scsi_cmd_pdu() error handling
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Mike Christie <[email protected]>
[ Upstream commit d28d48c699779973ab9a3bd0e5acfa112bd4fdef ]
If iscsi_prep_scsi_cmd_pdu() fails we try to add it back to the cmdqueue, but we leave it partially setup. We don't have functions that can undo the pdu and init task setup. We only have cleanup_task which can clean up both parts. So this has us just fail the cmd and go through the standard cleanup routine and then have the SCSI midlayer retry it like is done when it fails in the queuecommand path.
--- drivers/scsi/libiscsi.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-)
drivers/scsi/libiscsi.c +3 -8
@@ -1532,14 +1532,9 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) } rc =iscsi_prep_scsi_cmd_pdu (conn->task);if (rc) { -if (rc == -ENOMEM || rc == -EACCES ) { -spin_lock_bh (&conn->taskqueuelock); -list_add_tail (&conn->task->running, - &conn->cmdqueue); - conn->task =NULL ; -spin_unlock_bh (&conn->taskqueuelock); - goto done; - }else +if (rc == -ENOMEM || rc == -EACCES ) +fail_scsi_task (conn->task,DID_IMM_RETRY ); +else fail_scsi_task (conn->task,DID_ABORT );spin_lock_bh (&conn->taskqueuelock);continue ;
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 161/306 scsi: target: core: Add cmd length set before cmd complete
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Aleksandr Miloserdov <[email protected]>
[ Upstream commit 1c73e0c5e54d5f7d77f422a10b03ebe61eaed5ad ]
TCM doesn't properly handle underflow case for service actions. One way to prevent it is to always complete command with target_complete_cmd_with_length(), however it requires access to data_sg, which is not always available.
This change introduces target_set_cmd_data_length() function which allows to set command data length before completing it.
--- drivers/target/target_core_transport.c | 15 +++++++++++---- include/target/target_core_backend.h | 1 + 2 files changed, 12 insertions(+), 4 deletions(-)
drivers/target/target_core_transport.c +11 -4
@@ -879,11 +879,9 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) }EXPORT_SYMBOL (target_complete_cmd); -void target_complete_cmd_with_length (struct se_cmd *cmd,u8 scsi_status,int length) +void target_set_cmd_data_length (struct se_cmd *cmd,int length) { -if ((scsi_status ==SAM_STAT_GOOD || - cmd->se_cmd_flags &SCF_TREAT_READ_AS_NORMAL ) && - length < cmd->data_length) { +if (length < cmd->data_length) {if (cmd->se_cmd_flags &SCF_UNDERFLOW_BIT ) { cmd->residual_count += cmd->data_length - length; }else {
@@ -893,6 +891,15 @@ void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int len cmd->data_length = length; } +} +EXPORT_SYMBOL (target_set_cmd_data_length); + +void target_complete_cmd_with_length (struct se_cmd *cmd,u8 scsi_status,int length) +{ +if (scsi_status ==SAM_STAT_GOOD || + cmd->se_cmd_flags &SCF_TREAT_READ_AS_NORMAL ) { +target_set_cmd_data_length (cmd, length); + }target_complete_cmd (cmd, scsi_status); }
include/target/target_core_backend.h +1 -0
@@ -72,6 +72,7 @@ int transport_backend_register(const struct target_backend_ops *);void target_backend_unregister (const struct target_backend_ops *);void target_complete_cmd (struct se_cmd *,u8 ); +void target_set_cmd_data_length (struct se_cmd *,int );void target_complete_cmd_with_length (struct se_cmd *,u8 ,int );void transport_copy_sense_to_cmd (struct se_cmd *,unsigned char *);
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 162/306 scsi: target: core: Prevent underflow for service actions
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Aleksandr Miloserdov <[email protected]>
[ Upstream commit 14d24e2cc77411301e906a8cf41884739de192de ]
TCM buffer length doesn't necessarily equal 8 + ADDITIONAL LENGTH which might be considered an underflow in case of Data-In size being greater than 8 + ADDITIONAL LENGTH. So truncate buffer length to prevent underflow.
--- drivers/target/target_core_pr.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
drivers/target/target_core_pr.c +11 -4
@@ -3739,6 +3739,7 @@ core_scsi3_pri_read_keys(struct se_cmd *cmd)spin_unlock (&dev->t10_pr.registration_lock);put_unaligned_be32 (add_len, &buf[4 ]); +target_set_cmd_data_length (cmd,8 + add_len);transport_kunmap_data_sg (cmd);
@@ -3757,7 +3758,7 @@ core_scsi3_pri_read_reservation(struct se_cmd *cmd)struct t10_pr_registration *pr_reg;unsigned char *buf;u64 pr_res_key; -u32 add_len =16 ;/* Hardcoded to 16 when a reservation is held. */ +u32 add_len =0 ;if (cmd->data_length <8 ) { pr_err("PRIN SA READ_RESERVATIONS SCSI Data Length: %u"
@@ -3775,8 +3776,9 @@ core_scsi3_pri_read_reservation(struct se_cmd *cmd) pr_reg = dev->dev_pr_res_holder;if (pr_reg) {/* -* Set the hardcoded Additional Length +* Set the Additional Length to 16 when a reservation is held */ + add_len =16 ;put_unaligned_be32 (add_len, &buf[4 ]);if (cmd->data_length <22 )
@@ -3812,6 +3814,8 @@ core_scsi3_pri_read_reservation(struct se_cmd *cmd) (pr_reg->pr_res_type &0x0f ); } +target_set_cmd_data_length (cmd,8 + add_len); + err:spin_unlock (&dev->dev_reservation_lock);transport_kunmap_data_sg (cmd);
@@ -3830,7 +3834,7 @@ core_scsi3_pri_report_capabilities(struct se_cmd *cmd)struct se_device *dev = cmd->se_dev;struct t10_reservation *pr_tmpl = &dev->t10_pr;unsigned char *buf; -u16 add_len =8 ;/* Hardcoded to 8. */ +u16 len =8 ;/* Hardcoded to 8. */ if (cmd->data_length <6 ) { pr_err("PRIN SA REPORT_CAPABILITIES SCSI Data Length:"
@@ -3842,7 +3846,7 @@ core_scsi3_pri_report_capabilities(struct se_cmd *cmd)if (!buf)return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE ; -put_unaligned_be16 (add_len, &buf[0 ]); +put_unaligned_be16 (len, &buf[0 ]); buf[2 ] |=0x10 ;/* CRH: Compatible Reservation Hanlding bit. */ buf[2 ] |=0x08 ;/* SIP_C: Specify Initiator Ports Capable bit */ buf[2 ] |=0x04 ;/* ATP_C: All Target Ports Capable bit */
@@ -3871,6 +3875,8 @@ core_scsi3_pri_report_capabilities(struct se_cmd *cmd) buf[4 ] |=0x02 ;/* PR_TYPE_WRITE_EXCLUSIVE */ buf[5 ] |=0x01 ;/* PR_TYPE_EXCLUSIVE_ACCESS_ALLREG */ +target_set_cmd_data_length (cmd, len); +transport_kunmap_data_sg (cmd);return 0 ;
@@ -4031,6 +4037,7 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd)* Set ADDITIONAL_LENGTH */ put_unaligned_be32 (add_len, &buf[4 ]); +target_set_cmd_data_length (cmd,8 + add_len);transport_kunmap_data_sg (cmd);
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 163/306 clk: qcom: gpucc-msm8998: Add resets, cxc, fix flags on gpu_gx_gdsc
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: AngeloGioacchino Del Regno <[email protected]>
[ Upstream commit a59c16c80bd791878cf81d1d5aae508eeb2e73f1 ]
The GPU GX GDSC has GPU_GX_BCR reset and gfx3d_clk CXC, as stated on downstream kernels (and as verified upstream, because otherwise random lockups happen).
Also, add PWRSTS_RET and NO_RET_PERIPH: also as found downstream, and also as verified here, to avoid GPU related lockups it is necessary to force retain mem, but *not* peripheral when enabling this GDSC (and, of course, the inverse on disablement).
With this change, the GPU finally works flawlessly on my four different MSM8998 devices from two different manufacturers.
--- drivers/clk/qcom/gpucc-msm8998.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/clk/qcom/gpucc-msm8998.c +6 -2
@@ -253,12 +253,16 @@ static struct gdsc gpu_cx_gdsc = {static struct gdsc gpu_gx_gdsc = { .gdscr =0x1094 , .clamp_io_ctrl =0x130 , + .resets = (unsigned int []){GPU_GX_BCR }, + .reset_count =1 , + .cxcs = (unsigned int []){0x1098 }, + .cxc_count =1 , .pd = { .name ="gpu_gx" , }, .parent = &gpu_cx_gdsc.pd, - .pwrsts =PWRSTS_OFF_ON , - .flags =CLAMP_IO |AON_RESET , + .pwrsts =PWRSTS_OFF_ON |PWRSTS_RET , + .flags =CLAMP_IO |SW_RESET |AON_RESET |NO_RET_PERIPH , };static struct clk_regmap *gpucc_msm8998_clocks[] = {
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 164/306 ALSA: usb: Add Plantronics C320-M USB ctrl msg delay quirk
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: John Ernberg <[email protected]>
commit fc7c5c208eb7bc2df3a9f4234f14eca250001cb6 upstream.
The microphone in the Plantronics C320-M headset will randomly fail to initialize properly, at least when using Microsoft Teams. Introducing a 20ms delay on the control messages appears to resolve the issue.
--- sound/usb/quirks.c | 8 ++++++++ 1 file changed, 8 insertions(+)
sound/usb/quirks.c +8 -0
@@ -1670,6 +1670,14 @@ void snd_usb_ctl_msg_quirk(struct usb_de && (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)msleep (20 ); +/* +* Plantronics C320-M needs a delay to avoid random +* microhpone failures. +*/ +if (chip->usb_id ==USB_ID (0x047f ,0xc025 ) && + (requesttype &USB_TYPE_MASK ) ==USB_TYPE_CLASS ) +msleep (20 ); +/* Zoom R16/24, many Logitech(at least H650e/H570e/BCC950), * Jabra 550a, Kingston HyperX needs a tiny delay here, * otherwise requests like get/set frequency return
[email protected]
maintainerPATCH 165/306 ALSA: hda/hdmi: Cancel pending works before suspend
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Takashi Iwai <[email protected]>
commit eea46a0879bcca23e15071f9968c0f6e6596e470 upstream.
The per_pin->work might be still floating at the suspend, and this may hit the access to the hardware at an unexpected timing. Cancel the work properly at the suspend callback for avoiding the buggy access.
Note that the bug doesn't trigger easily in the recent kernels since the work is queued only when the repoll count is set, and usually it's only at the resume callback, but it's still possible to hit in theory.
--- sound/pci/hda/patch_hdmi.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
sound/pci/hda/patch_hdmi.c +13 -0
@@ -2472,6 +2472,18 @@ static void generic_hdmi_free(struct hda }#ifdef CONFIG_PM +static int generic_hdmi_suspend (struct hda_codec *codec) +{ +struct hdmi_spec *spec = codec->spec; +int pin_idx; + +for (pin_idx =0 ; pin_idx < spec->num_pins; pin_idx++) { +struct hdmi_spec_per_pin *per_pin =get_pin (spec, pin_idx); +cancel_delayed_work_sync (&per_pin->work); + } +return 0 ; +} +static int generic_hdmi_resume (struct hda_codec *codec) {struct hdmi_spec *spec = codec->spec;
@@ -2495,6 +2507,7 @@ static const struct hda_codec_ops generi .build_controls = generic_hdmi_build_controls, .unsol_event = hdmi_unsol_event, #ifdef CONFIG_PM + .suspend = generic_hdmi_suspend, .resume = generic_hdmi_resume,#endif };
[email protected]
maintainerPATCH 166/306 ALSA: hda/conexant: Add quirk for mute LED control on HP ZBook G5
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Takashi Iwai <[email protected]>
commit 56b26497bb4b7ff970612dc25a8a008c34463f7b upstream.
The mute and mic-mute LEDs on HP ZBook Studio G5 are controlled via GPIO bits 0x10 and 0x20, respectively, and we need the extra setup for those.
As the similar code is already present for other HP models but with different GPIO pins, this patch factors out the common helper code and applies those GPIO values for each model.
--- sound/pci/hda/patch_conexant.c | 62 +++++++++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 17 deletions(-)
sound/pci/hda/patch_conexant.c +45 -17
@@ -149,6 +149,21 @@ static int cx_auto_vmaster_mute_led(strureturn 0 ; } +static void cxt_init_gpio_led (struct hda_codec *codec) +{ +struct conexant_spec *spec = codec->spec; +unsigned int mask = spec->gpio_mute_led_mask | spec->gpio_mic_led_mask; + +if (mask) { +snd_hda_codec_write (codec,0x01 ,0 ,AC_VERB_SET_GPIO_MASK , + mask); +snd_hda_codec_write (codec,0x01 ,0 ,AC_VERB_SET_GPIO_DIRECTION , + mask); +snd_hda_codec_write (codec,0x01 ,0 ,AC_VERB_SET_GPIO_DATA , + spec->gpio_led); + } +} +static int cx_auto_init (struct hda_codec *codec) {struct conexant_spec *spec = codec->spec;
@@ -156,6 +171,7 @@ static int cx_auto_init(struct hda_codecif (!spec->dynamic_eapd)cx_auto_turn_eapd (codec, spec->num_eapds, spec->eapds, true); +cxt_init_gpio_led (codec);snd_hda_apply_fixup (codec,HDA_FIXUP_ACT_INIT );return 0 ;
@@ -215,6 +231,7 @@ enum {CXT_FIXUP_HP_SPECTRE ,CXT_FIXUP_HP_GATE_MIC ,CXT_FIXUP_MUTE_LED_GPIO , +CXT_FIXUP_HP_ZBOOK_MUTE_LED ,CXT_FIXUP_HEADSET_MIC , CXT_FIXUP_HP_MIC_NO_PRESENCE, };
@@ -654,31 +671,36 @@ static int cxt_gpio_micmute_update(strucreturn 0 ; } - -static void cxt_fixup_mute_led_gpio (struct hda_codec *codec, -const struct hda_fixup *fix,int action) +static void cxt_setup_mute_led (struct hda_codec *codec, +unsigned int mute,unsigned int mic_mute) {struct conexant_spec *spec = codec->spec; -static const struct hda_verb gpio_init[] = { - {0x01 ,AC_VERB_SET_GPIO_MASK ,0x03 }, - {0x01 ,AC_VERB_SET_GPIO_DIRECTION ,0x03 }, - {} - }; -if (action ==HDA_FIXUP_ACT_PRE_PROBE ) { + spec->gpio_led =0 ; + spec->mute_led_polarity =0 ; +if (mute) {snd_hda_gen_add_mute_led_cdev (codec, cxt_gpio_mute_update); - spec->gpio_led =0 ; - spec->mute_led_polarity =0 ; - spec->gpio_mute_led_mask =0x01 ; - spec->gpio_mic_led_mask =0x02 ; + spec->gpio_mute_led_mask = mute; + } +if (mic_mute) {snd_hda_gen_add_micmute_led_cdev (codec, cxt_gpio_micmute_update); + spec->gpio_mic_led_mask = mic_mute; } -snd_hda_add_verbs (codec, gpio_init); -if (spec->gpio_led) -snd_hda_codec_write (codec,0x01 ,0 ,AC_VERB_SET_GPIO_DATA , - spec->gpio_led); } +static void cxt_fixup_mute_led_gpio (struct hda_codec *codec, +const struct hda_fixup *fix,int action) +{ +if (action ==HDA_FIXUP_ACT_PRE_PROBE ) +cxt_setup_mute_led (codec,0x01 ,0x02 ); +} + +static void cxt_fixup_hp_zbook_mute_led (struct hda_codec *codec, +const struct hda_fixup *fix,int action) +{ +if (action ==HDA_FIXUP_ACT_PRE_PROBE ) +cxt_setup_mute_led (codec,0x10 ,0x20 ); +}/* ThinkPad X200 & co with cxt5051 */ static const struct hda_pintbl cxt_pincfg_lenovo_x200[] = {
@@ -839,6 +861,10 @@ static const struct hda_fixup cxt_fixups .type = HDA_FIXUP_FUNC, .v.func = cxt_fixup_mute_led_gpio, }, + [CXT_FIXUP_HP_ZBOOK_MUTE_LED] = { + .type = HDA_FIXUP_FUNC, + .v.func = cxt_fixup_hp_zbook_mute_led, + }, [CXT_FIXUP_HEADSET_MIC] = { .type = HDA_FIXUP_FUNC, .v.func = cxt_fixup_headset_mic,
@@ -917,6 +943,7 @@ static const struct snd_pci_quirk cxt506SND_PCI_QUIRK (0x103c ,0x8299 ,"HP 800 G3 SFF" ,CXT_FIXUP_HP_MIC_NO_PRESENCE ),SND_PCI_QUIRK (0x103c ,0x829a ,"HP 800 G3 DM" ,CXT_FIXUP_HP_MIC_NO_PRESENCE ),SND_PCI_QUIRK (0x103c ,0x8402 ,"HP ProBook 645 G4" ,CXT_FIXUP_MUTE_LED_GPIO ), +SND_PCI_QUIRK (0x103c ,0x8427 ,"HP ZBook Studio G5" ,CXT_FIXUP_HP_ZBOOK_MUTE_LED ),SND_PCI_QUIRK (0x103c ,0x8455 ,"HP Z2 G4" ,CXT_FIXUP_HP_MIC_NO_PRESENCE ),SND_PCI_QUIRK (0x103c ,0x8456 ,"HP Z2 G4 SFF" ,CXT_FIXUP_HP_MIC_NO_PRESENCE ), SND_PCI_QUIRK(0x103c, 0x8457, "HP Z2 G4 mini", CXT_FIXUP_HP_MIC_NO_PRESENCE),
@@ -956,6 +983,7 @@ static const struct hda_model_fixup cxt5 { .id = CXT_FIXUP_MUTE_LED_EAPD, .name = "mute-led-eapd" }, { .id = CXT_FIXUP_HP_DOCK, .name = "hp-dock" }, { .id = CXT_FIXUP_MUTE_LED_GPIO, .name = "mute-led-gpio" }, + { .id = CXT_FIXUP_HP_ZBOOK_MUTE_LED, .name = "hp-zbook-mute-led" }, { .id = CXT_FIXUP_HP_MIC_NO_PRESENCE, .name = "hp-mic-fix" }, {} };
[email protected]
maintainerPATCH 167/306 ALSA: hda/ca0132: Add Sound BlasterX AE-5 Plus support
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Simeon Simeonoff <[email protected]>
commit f15c5c11abfbf8909eb30598315ecbec2311cfdc upstream.
The new AE-5 Plus model has a different Subsystem ID compared to the non-plus model. Adding the new id to the list of quirks.
--- sound/pci/hda/patch_ca0132.c | 1 + 1 file changed, 1 insertion(+)
sound/pci/hda/patch_ca0132.c +1 -0
@@ -1309,6 +1309,7 @@ static const struct snd_pci_quirk ca0132SND_PCI_QUIRK (0x1102 ,0x0013 ,"Recon3D" ,QUIRK_R3D ),SND_PCI_QUIRK (0x1102 ,0x0018 ,"Recon3D" ,QUIRK_R3D ),SND_PCI_QUIRK (0x1102 ,0x0051 ,"Sound Blaster AE-5" ,QUIRK_AE5 ), +SND_PCI_QUIRK (0x1102 ,0x0191 ,"Sound Blaster AE-5 Plus" ,QUIRK_AE5 ), SND_PCI_QUIRK(0x1102, 0x0081, "Sound Blaster AE-7", QUIRK_AE7), {} };
[email protected]
maintainerPATCH 168/306 ALSA: hda: Drop the BATCH workaround for AMD controllers
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Takashi Iwai <[email protected]>
commit 28e96c1693ec1cdc963807611f8b5ad400431e82 upstream.
The commit c02f77d32d2c ("ALSA: hda - Workaround for crackled sound on AMD controller (1022:1457)") introduced a few workarounds for the recent AMD HD-audio controller, and one of them is the forced BATCH PCM mode so that PulseAudio avoids the timer-based scheduling. This was thought to cover for some badly working applications, but this actually worsens for more others. In total, this wasn't a good idea to enforce it.
This is a partial revert of the commit above for dropping the PCM BATCH enforcement part to recover from the regression again.
--- sound/pci/hda/hda_controller.c | 7 ------- 1 file changed, 7 deletions(-)
sound/pci/hda/hda_controller.c +0 -7
@@ -609,13 +609,6 @@ static int azx_pcm_open(struct snd_pcm_s20 , 178000000); -/* by some reason, the playback stream stalls on PulseAudio with -* tsched=1 when a capture stream triggers. Until we figure out the -* real cause, disable tsched mode by telling the PCM info flag. -*/ -if (chip->driver_caps &AZX_DCAPS_AMD_WORKAROUND ) - runtime->hw.info |=SNDRV_PCM_INFO_BATCH ; -if (chip->align_buffer_size)/* constrain buffer sizes to be multiple of 128 bytes. This is more efficient in terms of memory
[email protected]
maintainerPATCH 169/306 ALSA: hda: Flush pending unsolicited events before suspend
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Takashi Iwai <[email protected]>
commit 13661fc48461282e43fe8f76bf5bf449b3d40687 upstream.
The HD-audio controller driver processes the unsolicited events via its work asynchronously, and this might be pending when the system goes to suspend. When a lengthy event handling like ELD byte reads is running, this might trigger unexpected accesses among suspend/resume procedure, typically seen with Nvidia driver that still requires the handling via unsolicited event verbs for ELD updates.
This patch adds the flush of unsol_work to assure that pending events are processed before going into suspend.
--- sound/pci/hda/hda_intel.c | 2 ++ 1 file changed, 2 insertions(+)
sound/pci/hda/hda_intel.c +2 -0
@@ -1026,6 +1026,8 @@ static int azx_prepare(struct device *de chip = card->private_data; chip->pm_prepared =1 ; +flush_work (&azx_bus (chip)->unsol_work); +/* HDA controller always requires different WAKEEN for runtime suspend * and system suspend, so don't use direct-complete here. */
[email protected]
maintainerPATCH 170/306 ALSA: hda: Avoid spurious unsol event handling during S3/S4
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Takashi Iwai <[email protected]>
commit 5ff9dde42e8c72ed8102eb8cb62e03f9dc2103ab upstream.
When HD-audio bus receives unsolicited events during its system suspend/resume (S3 and S4) phase, the controller driver may still try to process events although the codec chips are already (or yet) powered down. This might screw up the codec communication, resulting in CORB/RIRB errors. Such events should be rather skipped, as the codec chip status such as the jack status will be fully refreshed at the system resume time.
Since we're tracking the system suspend/resume state in codec power.power_state field, let's add the check in the common unsol event handler entry point to filter out such events.
--- sound/pci/hda/hda_bind.c | 4 ++++ 1 file changed, 4 insertions(+)
sound/pci/hda/hda_bind.c +4 -0
@@ -47,6 +47,10 @@ static void hda_codec_unsol_event(structif (codec->bus->shutdown)return ; +/* ignore unsol events during system suspend/resume */ +if (codec->core.dev.power.power_state.event !=PM_EVENT_ON ) +return ; +if (codec->patch_ops.unsol_event) codec->patch_ops.unsol_event (codec, ev); }
[email protected]
maintainerPATCH 171/306 ALSA: usb-audio: Fix "cannot get freq eq" errors on Dell AE515 sound bar
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Takashi Iwai <[email protected]>
commit fec60c3bc5d1713db2727cdffc638d48f9c07dc3 upstream.
Dell AE515 sound bar (413c:a506) spews the error messages when the driver tries to read the current sample frequency, hence it needs to be on the list in snd_usb_get_sample_rate_quirk().
--- sound/usb/quirks.c | 1 + 1 file changed, 1 insertion(+)
sound/usb/quirks.c +1 -0
@@ -1520,6 +1520,7 @@ bool snd_usb_get_sample_rate_quirk(struccase USB_ID (0x1901 ,0x0191 ):/* GE B850V3 CP2114 audio interface */ case USB_ID (0x21b4 ,0x0081 ):/* AudioQuest DragonFly */ case USB_ID (0x2912 ,0x30c8 ):/* Audioengine D1 */ +case USB_ID (0x413c ,0xa506 ):/* Dell AE515 sound bar */ return true; }
[email protected]
maintainerPATCH 172/306 ALSA: usb-audio: Apply the control quirk to Plantronics headsets
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Takashi Iwai <[email protected]>
commit 06abcb18b3a021ba1a3f2020cbefb3ed04e59e72 upstream.
Other Plantronics headset models seem requiring the same workaround as C320-M to add the 20ms delay for the control messages, too. Apply the workaround generically for devices with the vendor ID 0x047f.
Note that the problem didn't surface before 5.11 just with luck. Since 5.11 got a big code rewrite about the stream handling, the parameter setup procedure has changed, and this seemed triggering the problem more often.
--- sound/usb/quirks.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
sound/usb/quirks.c +3 -3
@@ -1672,10 +1672,10 @@ void snd_usb_ctl_msg_quirk(struct usb_demsleep (20 );/* -* Plantronics C320-M needs a delay to avoid random -* microhpone failures. +* Plantronics headsets (C320, C320-M, etc) need a delay to avoid +* random microhpone failures. */ -if (chip->usb_id ==USB_ID (0x047f ,0xc025 ) && +if (USB_ID_VENDOR (chip->usb_id) ==0x047f && (requesttype &USB_TYPE_MASK ) ==USB_TYPE_CLASS )msleep (20 );
[email protected]
maintainerPATCH 173/306 ALSA: usb-audio: Disable USB autosuspend properly in setup_disable_autosuspend()
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Kai-Heng Feng <[email protected]>
commit 9799110825dba087c2bdce886977cf84dada2005 upstream.
Rear audio on Lenovo ThinkStation P620 stops working after commit 1965c4364bdd ("ALSA: usb-audio: Disable autosuspend for Lenovo ThinkStation P620"):
[ 6.013526] usbcore: registered new interface driver snd-usb-audio [ 6.023064] usb 3-6: cannot get ctl value: req = 0x81, wValue = 0x100, wIndex = 0x0, type = 1 [ 6.023083] usb 3-6: cannot get ctl value: req = 0x81, wValue = 0x202, wIndex = 0x0, type = 4 [ 6.023090] usb 3-6: cannot get ctl value: req = 0x81, wValue = 0x100, wIndex = 0x0, type = 1 [ 6.023098] usb 3-6: cannot get ctl value: req = 0x81, wValue = 0x202, wIndex = 0x0, type = 4 [ 6.023103] usb 3-6: cannot get ctl value: req = 0x81, wValue = 0x100, wIndex = 0x0, type = 1 [ 6.023110] usb 3-6: cannot get ctl value: req = 0x81, wValue = 0x202, wIndex = 0x0, type = 4 [ 6.045846] usb 3-6: cannot get ctl value: req = 0x81, wValue = 0x100, wIndex = 0x0, type = 1 [ 6.045866] usb 3-6: cannot get ctl value: req = 0x81, wValue = 0x202, wIndex = 0x0, type = 4 [ 6.045877] usb 3-6: cannot get ctl value: req = 0x81, wValue = 0x100, wIndex = 0x0, type = 1 [ 6.045886] usb 3-6: cannot get ctl value: req = 0x81, wValue = 0x202, wIndex = 0x0, type = 4 [ 6.045894] usb 3-6: cannot get ctl value: req = 0x81, wValue = 0x100, wIndex = 0x0, type = 1 [ 6.045908] usb 3-6: cannot get ctl value: req = 0x81, wValue = 0x202, wIndex = 0x0, type = 4
I overlooked the issue because when I was working on the said commit, only the front audio is tested. Apology for that.
Changing supports_autosuspend in driver is too late for disabling autosuspend, because it was already used by USB probe routine, so it can break the balance on the following code that depends on supports_autosuspend.
Fix it by using usb_disable_autosuspend() helper, and balance the suspend count in disconnect callback.
--- sound/usb/card.c | 5 +++++ sound/usb/quirks.c | 2 +- sound/usb/usbaudio.h | 1 + 3 files changed, 7 insertions(+), 1 deletion(-)
sound/usb/card.c +5 -0
@@ -831,6 +831,8 @@ static int usb_audio_probe(struct usb_insnd_media_device_create (chip, intf); } + chip->quirk_type = quirk->type; + usb_chip[chip->index] = chip; chip->intf[chip->num_interfaces] = intf; chip->num_interfaces++;
@@ -913,6 +915,9 @@ static void usb_audio_disconnect(struct }else {mutex_unlock (®ister_mutex); } + +if (chip->quirk_type &QUIRK_SETUP_DISABLE_AUTOSUSPEND ) +usb_enable_autosuspend (interface_to_usbdev (intf)); }/* lock the shutdown (disconnect) task and autoresume */
sound/usb/quirks.c +1 -1
@@ -547,7 +547,7 @@ static int setup_disable_autosuspend(strstruct usb_driver *driver, const struct snd_usb_audio_quirk *quirk) { - driver->supports_autosuspend = 0; +usb_disable_autosuspend (interface_to_usbdev (iface ));return 1 ;/* Continue with creating streams and mixer */ }
sound/usb/usbaudio.h +1 -0
@@ -27,6 +27,7 @@ struct snd_usb_audio {struct snd_card *card;struct usb_interface *intf[MAX_CARD_INTERFACES ];u32 usb_id; +uint16_t quirk_type;struct mutex mutex;unsigned int system_suspend;atomic_t active;
[email protected]
maintainerPATCH 174/306 ALSA: usb-audio: fix NULL ptr dereference in usb_audio_probe
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Pavel Skripkin <[email protected]>
commit 30dea07180de3aa0ad613af88431ef4e34b5ef68 upstream.
syzbot reported null pointer dereference in usb_audio_probe. The problem was in case, when quirk == NULL. It's not an error condition, so quirk must be checked before dereferencing.
Call Trace: usb_probe_interface+0x315/0x7f0 drivers/usb/core/driver.c:396 really_probe+0x291/0xe60 drivers/base/dd.c:554 driver_probe_device+0x26b/0x3d0 drivers/base/dd.c:740 __device_attach_driver+0x1d1/0x290 drivers/base/dd.c:846 bus_for_each_drv+0x15f/0x1e0 drivers/base/bus.c:431 __device_attach+0x228/0x4a0 drivers/base/dd.c:914 bus_probe_device+0x1e4/0x290 drivers/base/bus.c:491 device_add+0xbdb/0x1db0 drivers/base/core.c:3242 usb_set_configuration+0x113f/0x1910 drivers/usb/core/message.c:2164 usb_generic_driver_probe+0xba/0x100 drivers/usb/core/generic.c:238 usb_probe_device+0xd9/0x2c0 drivers/usb/core/driver.c:293 really_probe+0x291/0xe60 drivers/base/dd.c:554 driver_probe_device+0x26b/0x3d0 drivers/base/dd.c:740 __device_attach_driver+0x1d1/0x290 drivers/base/dd.c:846 bus_for_each_drv+0x15f/0x1e0 drivers/base/bus.c:431 __device_attach+0x228/0x4a0 drivers/base/dd.c:914 bus_probe_device+0x1e4/0x290 drivers/base/bus.c:491 device_add+0xbdb/0x1db0 drivers/base/core.c:3242 usb_new_device.cold+0x721/0x1058 drivers/usb/core/hub.c:2555 hub_port_connect drivers/usb/core/hub.c:5223 [inline] hub_port_connect_change drivers/usb/core/hub.c:5363 [inline] port_event drivers/usb/core/hub.c:5509 [inline] hub_event+0x2357/0x4320 drivers/usb/core/hub.c:5591 process_one_work+0x98d/0x1600 kernel/workqueue.c:2275 worker_thread+0x64c/0x1120 kernel/workqueue.c:2421 kthread+0x3b1/0x4a0 kernel/kthread.c:292 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:294
--- sound/usb/card.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
sound/usb/card.c +2 -1
@@ -831,7 +831,8 @@ static int usb_audio_probe(struct usb_insnd_media_device_create (chip, intf); } - chip->quirk_type = quirk->type; +if (quirk) + chip->quirk_type = quirk->type; usb_chip[chip->index] = chip; chip->intf[chip->num_interfaces] = intf;
[email protected]
maintainerPATCH 175/306 ALSA: usb-audio: fix use after free in usb_audio_disconnect
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Pavel Skripkin <[email protected]>
commit c5aa956eaeb05fe87e33433d7fd9f5e4d23c7416 upstream.
The problem was in wrong "if" placement. chip->quirk_type is freed in snd_card_free_when_closed(), but inside if statement it's accesed.
--- sound/usb/card.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
sound/usb/card.c +3 -3
@@ -908,6 +908,9 @@ static void usb_audio_disconnect(struct } } +if (chip->quirk_type &QUIRK_SETUP_DISABLE_AUTOSUSPEND ) +usb_enable_autosuspend (interface_to_usbdev (intf)); + chip->num_interfaces--;if (chip->num_interfaces <=0 ) { usb_chip[chip->index] =NULL ;
@@ -916,9 +919,6 @@ static void usb_audio_disconnect(struct }else {mutex_unlock (®ister_mutex); } - -if (chip->quirk_type &QUIRK_SETUP_DISABLE_AUTOSUSPEND ) -usb_enable_autosuspend (interface_to_usbdev (intf)); }/* lock the shutdown (disconnect) task and autoresume */
[email protected]
maintainerPATCH 176/306 opp: Dont drop extra references to OPPs accidentally
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Beata Michalska <[email protected]>
commit 606a5d4227e4610399c61086ac55c46068a90b03 upstream.
We are required to call dev_pm_opp_put() from outside of the opp_table->lock as debugfs removal needs to happen lock-less to avoid circular dependency issues.
commit cf1fac943c63 ("opp: Reduce the size of critical section in _opp_kref_release()") tried to fix that introducing a new routine _opp_get_next() which keeps returning OPPs that can be freed by the callers and this routine shall be called without holding the opp_table->lock.
Though the commit overlooked the fact that the OPPs can be referenced by other users as well and this routine will end up dropping references which were taken by other users and hence freeing the OPPs prematurely.
In effect, other users of the OPPs will end up having invalid pointers at hand. We didn't see any crash reports earlier as the exact situation never happened, though it is certainly possible.
We need a way to mark which OPPs are no longer referenced by the OPP core, so we don't drop extra references to them accidentally.
This commit adds another OPP flag, "removed", which is used to track this. And now we should never end up dropping extra references to the OPPs.
[ Viresh: Almost rewrote entire patch, added new "removed" field,
rewrote commit log and added the correct Fixes tag. ]
--- drivers/opp/core.c | 48 +++++++++++++++++++++++++----------------------- drivers/opp/opp.h | 2 ++ 2 files changed, 27 insertions(+), 23 deletions(-)
drivers/opp/core.c +25 -23
@@ -1335,7 +1335,11 @@ static struct dev_pm_opp *_opp_get_next(mutex_lock (&opp_table->lock);list_for_each_entry (temp, &opp_table->opp_list, node) { -if (dynamic == temp->dynamic) { +/* +* Refcount must be dropped only once for each OPP by OPP core, +* do that with help of "removed" flag. +*/ +if (!temp->removed && dynamic == temp->dynamic) { opp = temp;break ; }
@@ -1345,10 +1349,27 @@ static struct dev_pm_opp *_opp_get_next(return opp; } -bool _opp_remove_all_static (struct opp_table *opp_table) +/* +* Can't call dev_pm_opp_put() from under the lock as debugfs removal needs to +* happen lock less to avoid circular dependency issues. This routine must be +* called without the opp_table->lock held. +*/ +static void _opp_remove_all (struct opp_table *opp_table,bool dynamic) {struct dev_pm_opp *opp; +while ((opp =_opp_get_next (opp_table, dynamic))) { + opp->removed = true; +dev_pm_opp_put (opp); + +/* Drop the references taken by dev_pm_opp_add() */ +if (dynamic) +dev_pm_opp_put_opp_table (opp_table); + } +} + +bool _opp_remove_all_static (struct opp_table *opp_table) +{mutex_lock (&opp_table->lock);if (!opp_table->parsed_static_opps) {
@@ -1363,13 +1384,7 @@ bool _opp_remove_all_static(struct opp_tmutex_unlock (&opp_table->lock); -/* -* Can't remove the OPP from under the lock, debugfs removal needs to -* happen lock less to avoid circular dependency issues. -*/ -while ((opp =_opp_get_next (opp_table, false))) -dev_pm_opp_put (opp); - +_opp_remove_all (opp_table, false);return true; }
@@ -1382,25 +1397,12 @@ bool _opp_remove_all_static(struct opp_tvoid dev_pm_opp_remove_all_dynamic (struct device *dev) {struct opp_table *opp_table; -struct dev_pm_opp *opp; -int count =0 ; opp_table =_find_opp_table (dev);if (IS_ERR (opp_table))return ; -/* -* Can't remove the OPP from under the lock, debugfs removal needs to -* happen lock less to avoid circular dependency issues. -*/ -while ((opp =_opp_get_next (opp_table, true))) { -dev_pm_opp_put (opp); - count++; - } - -/* Drop the references taken by dev_pm_opp_add() */ -while (count--) -dev_pm_opp_put_opp_table (opp_table); +_opp_remove_all (opp_table, true);/* Drop the reference taken by _find_opp_table() */ dev_pm_opp_put_opp_table (opp_table);
drivers/opp/opp.h +2 -0
@@ -56,6 +56,7 @@ extern struct list_head opp_tables;* @dynamic: not-created from static DT entries. * @turbo: true if turbo (boost) OPP * @suspend: true if suspend OPP +* @removed: flag indicating that OPP's reference is dropped by OPP core. * @pstate: Device's power domain's performance state. * @rate: Frequency in hertz * @level: Performance level
@@ -78,6 +79,7 @@ struct dev_pm_opp {bool dynamic;bool turbo;bool suspend; +bool removed;unsigned int pstate;unsigned long rate;unsigned int level;
[email protected]
maintainerPATCH 177/306 Revert 95ebabde382c ("capabilities: Dont allow writing ambiguous v3 file capabilities")
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Eric W. Biederman <[email protected]>
commit 3b0c2d3eaa83da259d7726192cf55a137769012f upstream.
It turns out that there are in fact userspace implementations that care and this recent change caused a regression.
https://github.com/containers/buildah/issues/3071
As the motivation for the original change was future development, and the impact is existing real world code just revert this change and allow the ambiguity in v3 file caps.
--- security/commoncap.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-)
security/commoncap.c +1 -11
@@ -500,8 +500,7 @@ int cap_convert_nscap(struct dentry *den__u32 magic, nsmagic;struct inode *inode =d_backing_inode (dentry);struct user_namespace *task_ns =current_user_ns (), - *fs_ns = inode->i_sb->s_user_ns, - *ancestor; + *fs_ns = inode->i_sb->s_user_ns;kuid_t rootid;size_t newsize;
@@ -524,15 +523,6 @@ int cap_convert_nscap(struct dentry *denif (nsrootid ==-1 )return -EINVAL ; -/* -* Do not allow allow adding a v3 filesystem capability xattr -* if the rootid field is ambiguous. -*/ -for (ancestor = task_ns->parent; ancestor; ancestor = ancestor->parent) { -if (from_kuid (ancestor, rootid) ==0 ) -return -EINVAL ; - } - newsize =sizeof (struct vfs_ns_cap_data ); nscap =kmalloc (newsize,GFP_ATOMIC );if (!nscap)
[email protected]
maintainerPATCH 178/306 block: Discard page cache of zone reset target range
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Shin'ichiro Kawasaki <[email protected]>
commit e5113505904ea1c1c0e1f92c1cfa91fbf4da1694 upstream.
When zone reset ioctl and data read race for a same zone on zoned block devices, the data read leaves stale page cache even though the zone reset ioctl zero clears all the zone data on the device. To avoid non-zero data read from the stale page cache after zone reset, discard page cache of reset target zones in blkdev_zone_mgmt_ioctl(). Introduce the helper function blkdev_truncate_zone_range() to discard the page cache. Ensure the page cache discarded by calling the helper function before and after zone reset in same manner as fallocate does.
This patch can be applied back to the stable kernel version v5.10.y. Rework is needed for older stable kernels.
--- block/blk-zoned.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-)
block/blk-zoned.c +36 -2
@@ -318,6 +318,22 @@ int blkdev_report_zones_ioctl(struct bloreturn 0 ; } +static int blkdev_truncate_zone_range (struct block_device *bdev,fmode_t mode, +const struct blk_zone_range *zrange) +{ +loff_t start, end; + +if (zrange->sector + zrange->nr_sectors <= zrange->sector || + zrange->sector + zrange->nr_sectors >get_capacity (bdev->bd_disk)) +/* Out of range */ +return -EINVAL ; + + start = zrange->sector <<SECTOR_SHIFT ; + end = ((zrange->sector + zrange->nr_sectors) <<SECTOR_SHIFT ) -1 ; + +return truncate_bdev_range (bdev, mode, start, end); +} +/* * BLKRESETZONE, BLKOPENZONE, BLKCLOSEZONE and BLKFINISHZONE ioctl processing. * Called from blkdev_ioctl.
@@ -329,6 +345,7 @@ int blkdev_zone_mgmt_ioctl(struct block_struct request_queue *q;struct blk_zone_range zrange;enum req_opf op; +int ret;if (!argp)return -EINVAL ;
@@ -352,6 +369,11 @@ int blkdev_zone_mgmt_ioctl(struct block_switch (cmd) {case BLKRESETZONE : op =REQ_OP_ZONE_RESET ; + +/* Invalidate the page cache, including dirty pages. */ + ret =blkdev_truncate_zone_range (bdev, mode, &zrange); +if (ret) +return ret;break ;case BLKOPENZONE : op =REQ_OP_ZONE_OPEN ;
@@ -366,8 +388,20 @@ int blkdev_zone_mgmt_ioctl(struct block_return -ENOTTY ; } -return blkdev_zone_mgmt (bdev, op, zrange.sector, zrange.nr_sectors, -GFP_KERNEL ); + ret =blkdev_zone_mgmt (bdev, op, zrange.sector, zrange.nr_sectors, +GFP_KERNEL ); + +/* +* Invalidate the page cache again for zone reset: writes can only be +* direct for zoned devices so concurrent writes would not add any page +* to the page cache after/during reset. The page cache may be filled +* again due to concurrent reads though and dropping the pages for +* these is fine. +*/ +if (!ret && cmd ==BLKRESETZONE ) + ret =blkdev_truncate_zone_range (bdev, mode, &zrange); + +return ret; } static inline unsigned long *blk_alloc_zone_bitmap(int node,
[email protected]
maintainerPATCH 179/306 block: Try to handle busy underlying device on discard
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Jan Kara <[email protected]>
commit 56887cffe946bb0a90c74429fa94d6110a73119d upstream.
Commit 384d87ef2c95 ("block: Do not discard buffers under a mounted filesystem") made paths issuing discard or zeroout requests to the underlying device try to grab block device in exclusive mode. If that failed we returned EBUSY to userspace. This however caused unexpected fallout in userspace where e.g. FUSE filesystems issue discard requests from userspace daemons although the device is open exclusively by the kernel. Also shrinking of logical volume by LVM issues discard requests to a device which may be claimed exclusively because there's another LV on the same PV. So to avoid these userspace regressions, fall back to invalidate_inode_pages2_range() instead of returning EBUSY to userspace and return EBUSY only of that call fails as well (meaning that there's indeed someone using the particular device range we are trying to discard).
--- fs/block_dev.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
fs/block_dev.c +10 -1
@@ -118,13 +118,22 @@ int truncate_bdev_range(struct block_devif (!(mode &FMODE_EXCL )) {int err =bd_prepare_to_claim (bdev, truncate_bdev_range);if (err) -return err; + goto invalidate; }truncate_inode_pages_range (bdev->bd_inode->i_mapping, lstart, lend);if (!(mode &FMODE_EXCL ))bd_abort_claiming (bdev, truncate_bdev_range);return 0 ; + +invalidate: +/* +* Someone else has handle exclusively open. Try invalidating instead. +* The 'end' argument is inclusive so the rounding is safe. +*/ +return invalidate_inode_pages2_range (bdev->bd_inode->i_mapping, + lstart >>PAGE_SHIFT , + lend >>PAGE_SHIFT ); }EXPORT_SYMBOL (truncate_bdev_range);
[email protected]
maintainerPATCH 180/306 arm64: kasan: fix page_alloc tagging with DEBUG_VIRTUAL
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Andrey Konovalov <[email protected]>
commit 86c83365ab76e4b43cedd3ce07a07d32a4dc79ba upstream.
When CONFIG_DEBUG_VIRTUAL is enabled, the default page_to_virt() macro implementation from include/linux/mm.h is used. That definition doesn't account for KASAN tags, which leads to no tags on page_alloc allocations.
Provide an arm64-specific definition for page_to_virt() when CONFIG_DEBUG_VIRTUAL is enabled that takes care of KASAN tags.
--- arch/arm64/include/asm/memory.h | 5 +++++ 1 file changed, 5 insertions(+)
arch/arm64/include/asm/memory.h +5 -0
@@ -315,6 +315,11 @@ static inline void *phys_to_virt(phys_ad#define ARCH_PFN_OFFSET ((unsigned long)PHYS_PFN_OFFSET)#if !defined(CONFIG_SPARSEMEM_VMEMMAP ) || defined(CONFIG_DEBUG_VIRTUAL ) +#define page_to_virt (x) ({ \ + __typeof__(x) __page = x; \ + void *__addr = __va(page_to_phys(__page)); \ + (void *)__tag_set((const void *)__addr, page_kasan_tag(__page));\ +})#define virt_to_page (x) pfn_to_page(virt_to_pfn(x))#else #define page_to_virt (x) ({ \
[email protected]
maintainerPATCH 181/306 arm64: mte: Map hotplugged memory as Normal Tagged
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Catalin Marinas <[email protected]>
commit d15dfd31384ba3cb93150e5f87661a76fa419f74 upstream.
In a system supporting MTE, the linear map must allow reading/writing allocation tags by setting the memory type as Normal Tagged. Currently, this is only handled for memory present at boot. Hotplugged memory uses Normal non-Tagged memory.
Introduce pgprot_mhp() for hotplugged memory and use it in add_memory_resource(). The arm64 code maps pgprot_mhp() to pgprot_tagged().
Note that ZONE_DEVICE memory should not be mapped as Tagged and therefore setting the memory type in arch_add_memory() is not feasible.
--- arch/arm64/include/asm/pgtable-prot.h | 1 - arch/arm64/include/asm/pgtable.h | 3 +++ arch/arm64/mm/mmu.c | 3 ++- include/linux/pgtable.h | 4 ++++ mm/memory_hotplug.c | 2 +- 5 files changed, 10 insertions(+), 3 deletions(-)
arch/arm64/include/asm/pgtable-prot.h +0 -1
@@ -66,7 +66,6 @@ extern bool arm64_use_ng_mappings;#define _PAGE_DEFAULT (_PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL))#define PAGE_KERNEL __pgprot(PROT_NORMAL) -#define PAGE_KERNEL_TAGGED __pgprot(PROT_NORMAL_TAGGED)#define PAGE_KERNEL_RO __pgprot((PROT_NORMAL & ~PTE_WRITE) | PTE_RDONLY)#define PAGE_KERNEL_ROX __pgprot((PROT_NORMAL & ~(PTE_WRITE | PTE_PXN)) | PTE_RDONLY)#define PAGE_KERNEL_EXEC __pgprot(PROT_NORMAL & ~PTE_PXN)
arch/arm64/include/asm/pgtable.h +3 -0
@@ -486,6 +486,9 @@ static inline pmd_t pmd_mkdevmap(pmd_t p __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC) | PTE_PXN | PTE_UXN)#define pgprot_device (prot) \ __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRE) | PTE_PXN | PTE_UXN) +#define pgprot_tagged (prot) \ + __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_TAGGED)) +#define pgprot_mhp pgprot_tagged/* * DMA allocations for non-coherent devices use what the Arm architecture calls * "Normal non-cacheable" memory, which permits speculation, unaligned accesses
arch/arm64/mm/mmu.c +2 -1
@@ -512,7 +512,8 @@ static void __init map_mem(pgd_t *pgdp)* if MTE is present. Otherwise, it has the same attributes as * PAGE_KERNEL. */ -__map_memblock (pgdp, start, end,PAGE_KERNEL_TAGGED , flags); +__map_memblock (pgdp, start, end,pgprot_tagged (PAGE_KERNEL ), + flags); }/*
include/linux/pgtable.h +4 -0
@@ -912,6 +912,10 @@ static inline void ptep_modify_prot_comm#define pgprot_device pgprot_noncached#endif +#ifndef pgprot_mhp +#define pgprot_mhp (prot) (prot) +#endif +#ifdef CONFIG_MMU #ifndef pgprot_modify#define pgprot_modify pgprot_modify
mm/memory_hotplug.c +1 -1
@@ -1019,7 +1019,7 @@ static int online_memory_block(struct me*/ int __ref add_memory_resource (int nid,struct resource *res,mhp_t mhp_flags) { -struct mhp_params params = { .pgprot =PAGE_KERNEL }; +struct mhp_params params = { .pgprot =pgprot_mhp (PAGE_KERNEL ) };u64 start, size;bool new_node = false;int ret;
[email protected]
maintainerPATCH 182/306 arm64: perf: Fix 64-bit event counter read truncation
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Rob Herring <[email protected]>
commit 7bb8bc6eb550116c504fb25af8678b9d7ca2abc5 upstream.
Commit 0fdf1bb75953 ("arm64: perf: Avoid PMXEV* indirection") changed armv8pmu_read_evcntr() to return a u32 instead of u64. The result is silent truncation of the event counter when using 64-bit counters. Given the offending commit appears to have passed thru several folks, it seems likely this was a bad rebase after v8.5 PMU 64-bit counters landed.
--- arch/arm64/kernel/perf_event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/kernel/perf_event.c +1 -1
@@ -460,7 +460,7 @@ static inline int armv8pmu_counter_has_oreturn pmnc &BIT (ARMV8_IDX_TO_COUNTER (idx)); } -static inline u32 armv8pmu_read_evcntr (int idx) +static inline u64 armv8pmu_read_evcntr (int idx) {u32 counter =ARMV8_IDX_TO_COUNTER (idx);
[email protected]
maintainerPATCH 183/306 s390/dasd: fix hanging DASD driver unbind
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Stefan Haberland <[email protected]>
commit 7d365bd0bff3c0310c39ebaffc9a8458e036d666 upstream.
In case of an unbind of the DASD device driver the function dasd_generic_remove() is called which shuts down the device. Among others this functions removes the int_handler from the cdev. During shutdown the device cancels all outstanding IO requests and waits for completion of the clear request.
Unfortunately the clear interrupt will never be received when there is no interrupt handler connected.
Fix by moving the int_handler removal after the call to the state machine where no request or interrupt is outstanding.
--- drivers/s390/block/dasd.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/s390/block/dasd.c +1 -2
@@ -3503,8 +3503,6 @@ void dasd_generic_remove(struct ccw_devistruct dasd_device *device;struct dasd_block *block; - cdev->handler =NULL ; - device =dasd_device_from_cdev (cdev);if (IS_ERR (device)) {dasd_remove_sysfs_files (cdev);
@@ -3523,6 +3521,7 @@ void dasd_generic_remove(struct ccw_devi* no quite down yet. */ dasd_set_target_state (device,DASD_STATE_NEW ); + cdev->handler =NULL ;/* dasd_delete_device destroys the device reference. */ block = device->block;dasd_delete_device (device);
[email protected]
maintainerPATCH 184/306 s390/dasd: fix hanging IO request during DASD driver unbind
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Stefan Haberland <[email protected]>
commit 66f669a272898feb1c69b770e1504aa2ec7723d1 upstream.
Prevent that an IO request is build during device shutdown initiated by a driver unbind. This request will never be able to be processed or canceled and will hang forever. This will lead also to a hanging unbind.
Fix by checking not only if the device is in READY state but also check that there is no device offline initiated before building a new IO request.
--- drivers/s390/block/dasd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/s390/block/dasd.c +2 -1
@@ -3068,7 +3068,8 @@ static blk_status_t do_dasd_request(stru basedev = block->base;spin_lock_irq (&dq->lock); -if (basedev->state <DASD_STATE_READY ) { +if (basedev->state <DASD_STATE_READY || +test_bit (DASD_FLAG_OFFLINE , &basedev->flags)) {DBF_DEV_EVENT (DBF_ERR , basedev,"device not ready for request %p" , req); rc =BLK_STS_IOERR ;
[email protected]
maintainerPATCH 185/306 software node: Fix node registration
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Heikki Krogerus <[email protected]>
commit 8891123f9cbb9c1ee531e5a87fa116f0af685c48 upstream.
Software node can not be registered before its parent.
--- drivers/base/swnode.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/base/swnode.c +3 -0
@@ -786,6 +786,9 @@ int software_node_register(const structif (software_node_to_swnode (node))return -EEXIST ; +if (node->parent && !parent) +return -EINVAL ; +return PTR_ERR_OR_ZERO (swnode_register (node, parent,0 )); }EXPORT_SYMBOL_GPL (software_node_register);
[email protected]
maintainerPATCH 186/306 xen/events: reset affinity of 2-level event when tearing it down
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Juergen Gross <[email protected]>
commit 9e77d96b8e2724ed00380189f7b0ded61113b39f upstream.
When creating a new event channel with 2-level events the affinity needs to be reset initially in order to avoid using an old affinity from earlier usage of the event channel port. So when tearing an event channel down reset all affinity bits.
The same applies to the affinity when onlining a vcpu: all old affinity settings for this vcpu must be reset. As percpu events get initialized before the percpu event channel hook is called, resetting of the affinities happens after offlining a vcpu (this is working, as initial percpu memory is zeroed out).
--- drivers/xen/events/events_2l.c | 15 +++++++++++++++ drivers/xen/events/events_base.c | 1 + drivers/xen/events/events_internal.h | 8 ++++++++ 3 files changed, 24 insertions(+)
drivers/xen/events/events_2l.c +15 -0
@@ -47,6 +47,11 @@ static unsigned evtchn_2l_max_channels(vreturn EVTCHN_2L_NR_CHANNELS ; } +static void evtchn_2l_remove (evtchn_port_t evtchn,unsigned int cpu) +{ +clear_bit (evtchn,BM (per_cpu (cpu_evtchn_mask, cpu))); +} +static void evtchn_2l_bind_to_cpu (evtchn_port_t evtchn,unsigned int cpu,unsigned int old_cpu) {
@@ -355,9 +360,18 @@ static void evtchn_2l_resume(void) EVTCHN_2L_NR_CHANNELS/BITS_PER_EVTCHN_WORD); } +static int evtchn_2l_percpu_deinit (unsigned int cpu) +{ +memset (per_cpu (cpu_evtchn_mask, cpu),0 ,sizeof (xen_ulong_t) * +EVTCHN_2L_NR_CHANNELS /BITS_PER_EVTCHN_WORD ); + +return 0 ; +} +static const struct evtchn_ops evtchn_ops_2l = { .max_channels = evtchn_2l_max_channels, .nr_channels = evtchn_2l_max_channels, + .remove = evtchn_2l_remove, .bind_to_cpu = evtchn_2l_bind_to_cpu, .clear_pending = evtchn_2l_clear_pending, .set_pending = evtchn_2l_set_pending,
@@ -367,6 +381,7 @@ static const struct evtchn_ops evtchn_op .unmask = evtchn_2l_unmask, .handle_events = evtchn_2l_handle_events, .resume = evtchn_2l_resume, + .percpu_deinit = evtchn_2l_percpu_deinit, };void __init xen_evtchn_2l_init (void )
drivers/xen/events/events_base.c +1 -0
@@ -368,6 +368,7 @@ static int xen_irq_info_pirq_setup(unsigstatic void xen_irq_info_cleanup (struct irq_info *info) {set_evtchn_to_irq (info->evtchn,-1 ); +xen_evtchn_port_remove (info->evtchn, info->cpu); info->evtchn =0 ;channels_on_cpu_dec (info); }
drivers/xen/events/events_internal.h +8 -0
@@ -14,6 +14,7 @@ struct evtchn_ops {unsigned (*nr_channels)(void );int (*setup)(evtchn_port_t port); +void (*remove)(evtchn_port_t port,unsigned int cpu);void (*bind_to_cpu)(evtchn_port_t evtchn,unsigned int cpu,unsigned int old_cpu);
@@ -54,6 +55,13 @@ static inline int xen_evtchn_port_setup(return 0 ; } +static inline void xen_evtchn_port_remove (evtchn_port_t evtchn, +unsigned int cpu) +{ +if (evtchn_ops->remove) + evtchn_ops->remove (evtchn, cpu); +} +static inline void xen_evtchn_port_bind_to_cpu (evtchn_port_t evtchn,unsigned int cpu,unsigned int old_cpu)
[email protected]
maintainerPATCH 187/306 xen/events: dont unmask an event channel when an eoi is pending
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Juergen Gross <[email protected]>
commit 25da4618af240fbec6112401498301a6f2bc9702 upstream.
An event channel should be kept masked when an eoi is pending for it. When being migrated to another cpu it might be unmasked, though.
In order to avoid this keep three different flags for each event channel to be able to distinguish "normal" masking/unmasking from eoi related masking/unmasking and temporary masking. The event channel should only be able to generate an interrupt if all flags are cleared.
[boris -- corrected Fixed tag format]
--- drivers/xen/events/events_2l.c | 7 -- drivers/xen/events/events_base.c | 101 +++++++++++++++++++++++++++-------- drivers/xen/events/events_fifo.c | 7 -- drivers/xen/events/events_internal.h | 6 -- 4 files changed, 80 insertions(+), 41 deletions(-)
drivers/xen/events/events_2l.c +0 -7
@@ -77,12 +77,6 @@ static bool evtchn_2l_is_pending(evtchn_return sync_test_bit (port,BM (&s->evtchn_pending[0 ])); } -static bool evtchn_2l_test_and_set_mask (evtchn_port_t port) -{ -struct shared_info *s = HYPERVISOR_shared_info; -return sync_test_and_set_bit (port,BM (&s->evtchn_mask[0 ])); -} -static void evtchn_2l_mask (evtchn_port_t port) {struct shared_info *s = HYPERVISOR_shared_info;
@@ -376,7 +370,6 @@ static const struct evtchn_ops evtchn_op .clear_pending = evtchn_2l_clear_pending, .set_pending = evtchn_2l_set_pending, .is_pending = evtchn_2l_is_pending, - .test_and_set_mask = evtchn_2l_test_and_set_mask, .mask = evtchn_2l_mask, .unmask = evtchn_2l_unmask, .handle_events = evtchn_2l_handle_events,
drivers/xen/events/events_base.c +80 -21
208 lines not on this page · raw message
drivers/xen/events/events_fifo.c +0 -7
@@ -209,12 +209,6 @@ static bool evtchn_fifo_is_pending(evtchreturn sync_test_bit (EVTCHN_FIFO_BIT (PENDING , word),BM (word)); } -static bool evtchn_fifo_test_and_set_mask (evtchn_port_t port) -{ -event_word_t *word =event_word_from_port (port); -return sync_test_and_set_bit (EVTCHN_FIFO_BIT (MASKED , word),BM (word)); -} -static void evtchn_fifo_mask (evtchn_port_t port) {event_word_t *word =event_word_from_port (port);
@@ -423,7 +417,6 @@ static const struct evtchn_ops evtchn_op .clear_pending = evtchn_fifo_clear_pending, .set_pending = evtchn_fifo_set_pending, .is_pending = evtchn_fifo_is_pending, - .test_and_set_mask = evtchn_fifo_test_and_set_mask, .mask = evtchn_fifo_mask, .unmask = evtchn_fifo_unmask, .handle_events = evtchn_fifo_handle_events,
drivers/xen/events/events_internal.h +0 -6
@@ -21,7 +21,6 @@ struct evtchn_ops {void (*clear_pending)(evtchn_port_t port);void (*set_pending)(evtchn_port_t port);bool (*is_pending)(evtchn_port_t port); -bool (*test_and_set_mask)(evtchn_port_t port);void (*mask)(evtchn_port_t port);void (*unmask)(evtchn_port_t port);
@@ -84,11 +83,6 @@ static inline bool test_evtchn(evtchn_poreturn evtchn_ops->is_pending (port); } -static inline bool test_and_set_mask (evtchn_port_t port) -{ -return evtchn_ops->test_and_set_mask (port); -} -static inline void mask_evtchn (evtchn_port_t port) {return evtchn_ops->mask (port);
[email protected]
maintainerPATCH 188/306 xen/events: avoid handling the same event on two cpus at the same time
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Juergen Gross <[email protected]>
commit b6622798bc50b625a1e62f82c7190df40c1f5b21 upstream.
When changing the cpu affinity of an event it can happen today that (with some unlucky timing) the same event will be handled on the old and the new cpu at the same time.
Avoid that by adding an "event active" flag to the per-event data and call the handler only if this flag isn't set.
--- drivers/xen/events/events_base.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-)
drivers/xen/events/events_base.c +21 -11
@@ -102,6 +102,7 @@ struct irq_info {#define EVT_MASK_REASON_EXPLICIT 0x01#define EVT_MASK_REASON_TEMPORARY 0x02#define EVT_MASK_REASON_EOI_PENDING 0x04 +u8 is_active;/* Is event just being handled? */ unsigned irq;evtchn_port_t evtchn;/* event channel */ unsigned short cpu;/* cpu bound */
@@ -791,6 +792,12 @@ static void xen_evtchn_close(evtchn_portBUG (); } +static void event_handler_exit (struct irq_info *info) +{ +smp_store_release (&info->is_active,0 ); +clear_evtchn (info->evtchn); +} +static void pirq_query_unmask (int irq) {struct physdev_irq_status_query irq_status;
@@ -809,14 +816,15 @@ static void pirq_query_unmask(int irq)static void eoi_pirq (struct irq_data *data) { -evtchn_port_t evtchn =evtchn_from_irq (data->irq); +struct irq_info *info =info_for_irq (data->irq); +evtchn_port_t evtchn = info ? info->evtchn :0 ;struct physdev_eoi eoi = { .irq =pirq_from_irq (data->irq) };int rc =0 ;if (!VALID_EVTCHN (evtchn))return ; -clear_evtchn (evtchn); +event_handler_exit (info);if (pirq_needs_eoi (data->irq)) { rc =HYPERVISOR_physdev_op (PHYSDEVOP_eoi, &eoi);
@@ -1640,6 +1648,8 @@ void handle_irq_for_port(evtchn_port_t p } info =info_for_irq (irq); +if (xchg_acquire (&info->is_active,1 )) +return ;if (ctrl->defer_eoi) { info->eoi_cpu =smp_processor_id ();
@@ -1823,12 +1833,11 @@ static void disable_dynirq(struct irq_dastatic void ack_dynirq (struct irq_data *data) { -evtchn_port_t evtchn =evtchn_from_irq (data->irq); - -if (!VALID_EVTCHN (evtchn)) -return ; +struct irq_info *info =info_for_irq (data->irq); +evtchn_port_t evtchn = info ? info->evtchn :0 ; -clear_evtchn (evtchn); +if (VALID_EVTCHN (evtchn)) +event_handler_exit (info); }static void mask_ack_dynirq (struct irq_data *data)
@@ -1844,7 +1853,7 @@ static void lateeoi_ack_dynirq(struct irif (VALID_EVTCHN (evtchn)) {do_mask (info,EVT_MASK_REASON_EOI_PENDING ); -clear_evtchn (evtchn); +event_handler_exit (info); } }
@@ -1855,7 +1864,7 @@ static void lateeoi_mask_ack_dynirq(struif (VALID_EVTCHN (evtchn)) {do_mask (info,EVT_MASK_REASON_EXPLICIT ); -clear_evtchn (evtchn); +event_handler_exit (info); } }
@@ -1968,10 +1977,11 @@ static void restore_cpu_ipis(unsigned in/* Clear an irq's pending state, in preparation for polling on it */ void xen_clear_irq_pending (int irq) { -evtchn_port_t evtchn =evtchn_from_irq (irq); +struct irq_info *info =info_for_irq (irq); +evtchn_port_t evtchn = info ? info->evtchn :0 ;if (VALID_EVTCHN (evtchn)) -clear_evtchn (evtchn); +event_handler_exit (info); }EXPORT_SYMBOL (xen_clear_irq_pending);void xen_set_irq_pending (int irq)
[email protected]
maintainerPATCH 189/306 mmc: mmci: Add MMC_CAP_NEED_RSP_BUSY for the stm32 variants
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Yann Gautier <[email protected]>
commit 774514bf977377c9137640a0310bd64eed0f7323 upstream.
An issue has been observed on STM32MP157C-EV1 board, with an erase command with secure erase argument, ending up waiting for ~4 hours before timeout.
The requested busy timeout from the mmc core ends up with 14784000ms (~4 hours), but the supported host->max_busy_timeout is 86767ms, which leads to that the core switch to use an R1 response in favor of the R1B and polls for busy with the host->card_busy() ops. In this case the polling doesn't work as expected, as we never detects that the card stops signaling busy, which leads to the following message:
mmc1: Card stuck being busy! __mmc_poll_for_busy
The problem boils done to that the stm32 variants can't use R1 responses in favor of R1B responses, as it leads to an internal state machine in the controller to get stuck. To continue to process requests, it would need to be reset.
To fix this problem, let's set MMC_CAP_NEED_RSP_BUSY for the stm32 variant, which prevent the mmc core from switching to R1 responses. Additionally, let's cap the cmd->busy_timeout to the host->max_busy_timeout, thus rely on 86767ms to be sufficient (~66 seconds was need for this test case).
--- drivers/mmc/host/mmci.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
drivers/mmc/host/mmci.c +9 -1
@@ -1241,7 +1241,11 @@ mmci_start_command(struct mmci_host *hosif (!cmd->busy_timeout) cmd->busy_timeout =10 *MSEC_PER_SEC ; - clks = (unsigned long long )cmd->busy_timeout * host->cclk; +if (cmd->busy_timeout > host->mmc->max_busy_timeout) + clks = (unsigned long long )host->mmc->max_busy_timeout * host->cclk; +else + clks = (unsigned long long )cmd->busy_timeout * host->cclk; +do_div (clks,MSEC_PER_SEC );writel_relaxed (clks, host->base +MMCIDATATIMER ); }
@@ -2091,6 +2095,10 @@ static int mmci_probe(struct amba_device mmc->caps |=MMC_CAP_WAIT_WHILE_BUSY ; } +/* Variants with mandatory busy timeout in HW needs R1B responses. */ +if (variant->busy_timeout) + mmc->caps |=MMC_CAP_NEED_RSP_BUSY ; +/* Prepare a CMD12 - needed to clear the DPSM on some variants. */ host->stop_abort.opcode =MMC_STOP_TRANSMISSION ; host->stop_abort.arg =0 ;
[email protected]
maintainerPATCH 190/306 mmc: core: Fix partition switch time for eMMC
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Adrian Hunter <[email protected]>
commit 66fbacccbab91e6e55d9c8f1fc0910a8eb6c81f7 upstream.
Avoid the following warning by always defining partition switch time:
[ 3.209874] mmc1: unspecified timeout for CMD6 - use generic [ 3.222780] ------------[ cut here ]------------ [ 3.233363] WARNING: CPU: 1 PID: 111 at drivers/mmc/core/mmc_ops.c:575 __mmc_switch+0x200/0x204
--- drivers/mmc/core/mmc.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
drivers/mmc/core/mmc.c +11 -4
@@ -423,10 +423,6 @@ static int mmc_decode_ext_csd(struct mmc/* EXT_CSD value is in units of 10ms, but we store in ms */ card->ext_csd.part_time =10 * ext_csd[EXT_CSD_PART_SWITCH_TIME ]; -/* Some eMMC set the value too low so set a minimum */ -if (card->ext_csd.part_time && - card->ext_csd.part_time <MMC_MIN_PART_SWITCH_TIME ) - card->ext_csd.part_time =MMC_MIN_PART_SWITCH_TIME ;/* Sleep / awake timeout in 100ns units */ if (sa_shift >0 && sa_shift <=0x17 )
@@ -616,6 +612,17 @@ static int mmc_decode_ext_csd(struct mmc card->ext_csd.data_sector_size =512 ; } +/* +* GENERIC_CMD6_TIME is to be used "unless a specific timeout is defined +* when accessing a specific field", so use it here if there is no +* PARTITION_SWITCH_TIME. +*/ +if (!card->ext_csd.part_time) + card->ext_csd.part_time = card->ext_csd.generic_cmd6_time; +/* Some eMMC set the value too low so set a minimum */ +if (card->ext_csd.part_time <MMC_MIN_PART_SWITCH_TIME ) + card->ext_csd.part_time =MMC_MIN_PART_SWITCH_TIME ; +/* eMMC v5 or later */ if (card->ext_csd.rev >=7 ) { memcpy(card->ext_csd.fwrev, &ext_csd[EXT_CSD_FIRMWARE_VERSION],
[email protected]
maintainerPATCH 191/306 mmc: cqhci: Fix random crash when remove mmc module/card
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Frank Li <[email protected]>
commit f06391c45e83f9a731045deb23df7cc3814fd795 upstream.
[ 6684.493350] Unable to handle kernel paging request at virtual address ffff800011c5b0f0 [ 6684.498531] mmc0: card 0001 removed [ 6684.501556] Mem abort info: [ 6684.509681] ESR = 0x96000047 [ 6684.512786] EC = 0x25: DABT (current EL), IL = 32 bits [ 6684.518394] SET = 0, FnV = 0 [ 6684.521707] EA = 0, S1PTW = 0 [ 6684.524998] Data abort info: [ 6684.528236] ISV = 0, ISS = 0x00000047 [ 6684.532986] CM = 0, WnR = 1 [ 6684.536129] swapper pgtable: 4k pages, 48-bit VAs, pgdp=0000000081b22000 [ 6684.543923] [ffff800011c5b0f0] pgd=00000000bffff003, p4d=00000000bffff003, pud=00000000bfffe003, pmd=00000000900e1003, pte=0000000000000000 [ 6684.557915] Internal error: Oops: 96000047 [#1] PREEMPT SMP [ 6684.564240] Modules linked in: sdhci_esdhc_imx(-) sdhci_pltfm sdhci cqhci mmc_block mmc_core fsl_jr_uio caam_jr caamkeyblob_desc caamhash_desc caamalg_desc crypto_engine rng_core authenc libdes crct10dif_ce flexcan can_dev caam error [last unloaded: mmc_core] [ 6684.587281] CPU: 0 PID: 79138 Comm: kworker/0:3H Not tainted 5.10.9-01410-g3ba33182767b-dirty #10 [ 6684.596160] Hardware name: Freescale i.MX8DXL EVK (DT) [ 6684.601320] Workqueue: kblockd blk_mq_run_work_fn
[ 6684.606094] pstate: 40000005 (nZcv daif -PAN -UAO -TCO BTYPE=--) [ 6684.612286] pc : cqhci_request+0x148/0x4e8 [cqhci] ^GMessage from syslogd@ at Thu Jan 1 01:51:24 1970 ...[ 6684.617085] lr : cqhci_request+0x314/0x4e8 [cqhci] [ 6684.626734] sp : ffff80001243b9f0 [ 6684.630049] x29: ffff80001243b9f0 x28: ffff00002c3dd000 [ 6684.635367] x27: 0000000000000001 x26: 0000000000000001 [ 6684.640690] x25: ffff00002c451000 x24: 000000000000000f [ 6684.646007] x23: ffff000017e71c80 x22: ffff00002c451000 [ 6684.651326] x21: ffff00002c0f3550 x20: ffff00002c0f3550 [ 6684.656651] x19: ffff000017d46880 x18: ffff00002cea1500 [ 6684.661977] x17: 0000000000000000 x16: 0000000000000000 [ 6684.667294] x15: 000001ee628e3ed1 x14: 0000000000000278 [ 6684.672610] x13: 0000000000000001 x12: 0000000000000001 [ 6684.677927] x11: 0000000000000000 x10: 0000000000000000 [ 6684.683243] x9 : 000000000000002b x8 : 0000000000001000 [ 6684.688560] x7 : 0000000000000010 x6 : ffff00002c0f3678 [ 6684.693886] x5 : 000000000000000f x4 : ffff800011c5b000 [ 6684.699211] x3 : 000000000002d988 x2 : 0000000000000008 [ 6684.704537] x1 : 00000000000000f0 x0 : 0002d9880008102f [ 6684.709854] Call trace: [ 6684.712313] cqhci_request+0x148/0x4e8 [cqhci] [ 6684.716803] mmc_cqe_start_req+0x58/0x68 [mmc_core] [ 6684.721698] mmc_blk_mq_issue_rq+0x460/0x810 [mmc_block] [ 6684.727018] mmc_mq_queue_rq+0x118/0x2b0 [mmc_block]
The problem occurs when cqhci_request() get called after cqhci_disable() as it leads to access of allocated memory that has already been freed. Let's fix the problem by calling cqhci_disable() a bit later in the remove path.
--- drivers/mmc/core/bus.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
drivers/mmc/core/bus.c +5 -6
@@ -399,11 +399,6 @@ void mmc_remove_card(struct mmc_card *cammc_remove_card_debugfs (card);#endif -if (host->cqe_enabled) { - host->cqe_ops->cqe_disable (host); - host->cqe_enabled = false; - } -if (mmc_card_present (card)) {if (mmc_host_is_spi (card->host)) { pr_info("%s: SPI card removed\n",
@@ -416,6 +411,10 @@ void mmc_remove_card(struct mmc_card *caof_node_put (card->dev.of_node); } +if (host->cqe_enabled) { + host->cqe_ops->cqe_disable (host); + host->cqe_enabled = false; + } +put_device (&card->dev); } -
[email protected]
maintainerPATCH 192/306 cifs: do not send close in compound create+close requests
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Paulo Alcantara <[email protected]>
commit 04ad69c342fc4de5bd23be9ef15ea7574fb1a87e upstream.
In case of interrupted syscalls, prevent sending CLOSE commands for compound CREATE+CLOSE requests by introducing an CIFS_CP_CREATE_CLOSE_OP flag to indicate lower layers that it should not send a CLOSE command to the MIDs corresponding the compound CREATE+CLOSE request.
A simple reproducer:
#!/bin/bash
mount //server/share /mnt -o username=foo,password=*** tc qdisc add dev eth0 root netem delay 450ms stat -f /mnt &>/dev/null & pid=$!
sleep 0.01
kill $pid
tc qdisc del dev eth0 root
umount /mnt
Before patch:
...
6 0.256893470 192.168.122.2 → 192.168.122.15 SMB2 402 Create Request File: ;GetInfo Request FS_INFO/FileFsFullSizeInformation;Close Request
7 0.257144491 192.168.122.15 → 192.168.122.2 SMB2 498 Create Response File: ;GetInfo Response;Close Response
9 0.260798209 192.168.122.2 → 192.168.122.15 SMB2 146 Close Request File: 10 0.260841089 192.168.122.15 → 192.168.122.2 SMB2 130 Close Response, Error: STATUS_FILE_CLOSED
--- fs/cifs/cifsglob.h | 11 ++++++----- fs/cifs/smb2inode.c | 1 + fs/cifs/smb2misc.c | 8 ++++---- fs/cifs/smb2ops.c | 10 +++++----- fs/cifs/smb2proto.h | 3 +-- fs/cifs/transport.c | 2 +- 6 files changed, 18 insertions(+), 17 deletions(-)
fs/cifs/cifsglob.h +6 -5
@@ -256,7 +256,7 @@ struct smb_version_operations {/* verify the message */ int (*check_message)(char *,unsigned int ,struct TCP_Server_Info *);bool (*is_oplock_break)(char *,struct TCP_Server_Info *); -int (*handle_cancelled_mid)(char *,struct TCP_Server_Info *); +int (*handle_cancelled_mid)(struct mid_q_entry *,struct TCP_Server_Info *);void (*downgrade_oplock)(struct TCP_Server_Info *server,struct cifsInodeInfo *cinode,__u32 oplock,unsigned int epoch,bool *purge_cache);
@@ -1701,10 +1701,11 @@ static inline bool is_retryable_error(in#define CIFS_NO_RSP_BUF 0x040/* no response buffer required */ /* Type of request operation */ -#define CIFS_ECHO_OP 0x080/* echo request */ -#define CIFS_OBREAK_OP 0x0100/* oplock break request */ -#define CIFS_NEG_OP 0x0200/* negotiate request */ -#define CIFS_OP_MASK 0x0380/* mask request type */ +#define CIFS_ECHO_OP 0x080/* echo request */ +#define CIFS_OBREAK_OP 0x0100/* oplock break request */ +#define CIFS_NEG_OP 0x0200/* negotiate request */ +#define CIFS_CP_CREATE_CLOSE_OP 0x0400/* compound create+close request */ +#define CIFS_OP_MASK 0x0780/* mask request type */ #define CIFS_HAS_CREDITS 0x0400/* already has credits */ #define CIFS_TRANSFORM_REQ 0x0800/* transform request before sending */
fs/cifs/smb2inode.c +1 -0
@@ -358,6 +358,7 @@ smb2_compound_op(const unsigned int xid,if (cfile) goto after_close;/* Close */ + flags |=CIFS_CP_CREATE_CLOSE_OP ; rqst[num_rqst].rq_iov = &vars->close_iov[0 ]; rqst[num_rqst].rq_nvec =1 ; rc = SMB2_close_init(tcon, server,
fs/cifs/smb2misc.c +4 -4
@@ -844,14 +844,14 @@ smb2_handle_cancelled_close(struct cifs_ }int -smb2_handle_cancelled_mid (char *buffer,struct TCP_Server_Info *server) +smb2_handle_cancelled_mid (struct mid_q_entry *mid,struct TCP_Server_Info *server) { -struct smb2_sync_hdr *sync_hdr = (struct smb2_sync_hdr *)buffer; -struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)buffer; +struct smb2_sync_hdr *sync_hdr = mid->resp_buf; +struct smb2_create_rsp *rsp = mid->resp_buf;struct cifs_tcon *tcon;int rc; -if (sync_hdr->Command !=SMB2_CREATE || +if ((mid->optype &CIFS_CP_CREATE_CLOSE_OP ) || sync_hdr->Command !=SMB2_CREATE || sync_hdr->Status !=STATUS_SUCCESS )return 0 ;
fs/cifs/smb2ops.c +5 -5
@@ -1164,7 +1164,7 @@ smb2_set_ea(const unsigned int xid, strustruct TCP_Server_Info *server =cifs_pick_channel (ses);__le16 *utf16_path =NULL ;int ea_name_len =strlen (ea_name); -int flags =0 ; +int flags =CIFS_CP_CREATE_CLOSE_OP ;int len;struct smb_rqst rqst[3 ];int resp_buftype[3 ];
@@ -1542,7 +1542,7 @@ smb2_ioctl_query_info(const unsigned intstruct smb_query_info qi;struct smb_query_info __user *pqi;int rc =0 ; -int flags =0 ; +int flags =CIFS_CP_CREATE_CLOSE_OP ;struct smb2_query_info_rsp *qi_rsp =NULL ;struct smb2_ioctl_rsp *io_rsp =NULL ;void *buffer =NULL ;
@@ -2516,7 +2516,7 @@ smb2_query_info_compound(const unsigned {struct cifs_ses *ses = tcon->ses;struct TCP_Server_Info *server =cifs_pick_channel (ses); -int flags =0 ; +int flags =CIFS_CP_CREATE_CLOSE_OP ;struct smb_rqst rqst[3 ];int resp_buftype[3 ];struct kvec rsp_iov[3 ];
@@ -2914,7 +2914,7 @@ smb2_query_symlink(const unsigned int xiunsigned int sub_offset;unsigned int print_len;unsigned int print_offset; -int flags =0 ; +int flags =CIFS_CP_CREATE_CLOSE_OP ;struct smb_rqst rqst[3 ];int resp_buftype[3 ];struct kvec rsp_iov[3 ];
@@ -3096,7 +3096,7 @@ smb2_query_reparse_tag(const unsigned instruct cifs_open_parms oparms;struct cifs_fid fid;struct TCP_Server_Info *server =cifs_pick_channel (tcon->ses); -int flags =0 ; +int flags =CIFS_CP_CREATE_CLOSE_OP ;struct smb_rqst rqst[3 ];int resp_buftype[3 ];struct kvec rsp_iov[3 ];
fs/cifs/smb2proto.h +1 -2
@@ -246,8 +246,7 @@ extern int SMB2_oplock_break(const unsigextern int smb2_handle_cancelled_close (struct cifs_tcon *tcon,__u64 persistent_fid,__u64 volatile_fid); -extern int smb2_handle_cancelled_mid (char *buffer, -struct TCP_Server_Info *server); +extern int smb2_handle_cancelled_mid (struct mid_q_entry *mid,struct TCP_Server_Info *server);void smb2_cancelled_close_fid (struct work_struct *work); extern int SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_file_id, u64 volatile_file_id,
fs/cifs/transport.c +1 -1
@@ -101,7 +101,7 @@ static void _cifs_mid_q_entry_release(stif (midEntry->resp_buf && (midEntry->mid_flags &MID_WAIT_CANCELLED ) && midEntry->mid_state ==MID_RESPONSE_RECEIVED && server->ops->handle_cancelled_mid) - server->ops->handle_cancelled_mid (midEntry->resp_buf, server); + server->ops->handle_cancelled_mid (midEntry, server); midEntry->mid_state =MID_FREE ;atomic_dec (&midCount);
[email protected]
maintainerPATCH 193/306 Goodix Fingerprint device is not a modem
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Yorick de Wid <[email protected]>
commit 4d8654e81db7346f915eca9f1aff18f385cab621 upstream.
The CDC ACM driver is false matching the Goodix Fingerprint device against the USB_CDC_ACM_PROTO_AT_V25TER.
The Goodix Fingerprint device is a biometrics sensor that should be handled in user-space. libfprint has some support for Goodix fingerprint sensors, although not for this particular one. It is possible that the vendor allocates a PID per OEM (Lenovo, Dell etc). If this happens to be the case then more devices from the same vendor could potentially match the ACM modem module table.
--- drivers/usb/class/cdc-acm.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/usb/class/cdc-acm.c +5 -0
@@ -1929,6 +1929,11 @@ static const struct usb_device_id acm_id .driver_info = SEND_ZERO_PACKET, }, +/* Exclude Goodix Fingerprint Reader */ + { USB_DEVICE(0x27c6, 0x5395), + .driver_info =IGNORE_DEVICE , + }, + /* control interfaces without any protocol set */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, USB_CDC_PROTO_NONE) },
[email protected]
maintainerPATCH 194/306 USB: gadget: udc: s3c2410_udc: fix return value check in s3c2410_udc_probe()
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Wei Yongjun <[email protected]>
commit 414c20df7d401bcf1cb6c13d2dd944fb53ae4acf upstream.
In case of error, the function devm_platform_ioremap_resource() returns ERR_PTR() and never returns NULL. The NULL test in the return value check should be replaced with IS_ERR().
--- drivers/usb/gadget/udc/s3c2410_udc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/usb/gadget/udc/s3c2410_udc.c +2 -2
@@ -1773,8 +1773,8 @@ static int s3c2410_udc_probe(struct plat udc_info =dev_get_platdata (&pdev->dev); base_addr =devm_platform_ioremap_resource (pdev,0 ); -if (!base_addr) { - retval = -ENOMEM ; +if (IS_ERR (base_addr)) { + retval =PTR_ERR (base_addr); goto err_mem; }
[email protected]
maintainerPATCH 195/306 USB: gadget: u_ether: Fix a configfs return code
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Dan Carpenter <[email protected]>
commit 650bf52208d804ad5ee449c58102f8dc43175573 upstream.
If the string is invalid, this should return -EINVAL instead of 0.
--- drivers/usb/gadget/function/u_ether_configfs.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/usb/gadget/function/u_ether_configfs.h +2 -3
@@ -169,12 +169,11 @@ out: \ size_t len) \ { \ struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ -int ret; \ +int ret = -EINVAL ; \u8 val; \ \mutex_lock (&opts->lock); \ - ret =sscanf (page,"%02hhx" , &val); \ -if (ret >0 ) { \ +if (sscanf (page,"%02hhx" , &val) >0 ) { \ opts->_n_ = val; \ ret = len; \ } \
[email protected]
maintainerPATCH 196/306 usb: gadget: f_uac2: always increase endpoint max_packet_size by one audio slot
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Ruslan Bilovol <[email protected]>
commit 789ea77310f0200c84002884ffd628e2baf3ad8a upstream.
As per UAC2 Audio Data Formats spec (2.3.1.1 USB Packets), if the sampling rate is a constant, the allowable variation of number of audio slots per virtual frame is +/- 1 audio slot.
It means that endpoint should be able to accept/send +1 audio slot.
Previous endpoint max_packet_size calculation code was adding sometimes +1 audio slot due to DIV_ROUND_UP behaviour which was rounding up to closest integer. However this doesn't work if the numbers are divisible.
It had no any impact with Linux hosts which ignore this issue, but in case of more strict Windows it caused rejected enumeration
Thus always add +1 audio slot to endpoint's max packet size
--- drivers/usb/gadget/function/f_uac2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/gadget/function/f_uac2.c +1 -1
@@ -478,7 +478,7 @@ static int set_ep_max_packet_size(const } max_size_bw =num_channels (chmask) * ssize * -DIV_ROUND_UP (srate, factor / (1 << (ep_desc->bInterval -1 ))); + ((srate / (factor / (1 << (ep_desc->bInterval -1 )))) +1 ); ep_desc->wMaxPacketSize =cpu_to_le16 (min_t (u16, max_size_bw, max_size_ep));
[email protected]
maintainerPATCH 197/306 usb: gadget: f_uac1: stop playback on function disable
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Ruslan Bilovol <[email protected]>
commit cc2ac63d4cf72104e0e7f58bb846121f0f51bb19 upstream.
There is missing playback stop/cleanup in case of gadget's ->disable callback that happens on events like USB host resetting or gadget disconnection
--- drivers/usb/gadget/function/f_uac1.c | 1 + 1 file changed, 1 insertion(+)
drivers/usb/gadget/function/f_uac1.c +1 -0
@@ -499,6 +499,7 @@ static void f_audio_disable(struct usb_f uac1->as_out_alt =0 ; uac1->as_in_alt =0 ; +u_audio_stop_playback (&uac1->g_audio);u_audio_stop_capture (&uac1->g_audio); }
[email protected]
maintainerPATCH 198/306 usb: dwc3: qcom: Add missing DWC3 OF node refcount decrement
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Serge Semin <[email protected]>
commit 1cffb1c66499a9db9a735473778abf8427d16287 upstream.
of_get_child_by_name() increments the reference counter of the OF node it managed to find. So after the code is done using the device node, the refcount must be decremented. Add missing of_node_put() invocation then to the dwc3_qcom_of_register_core() method, since DWC3 OF node is being used only there.
--- drivers/usb/dwc3/dwc3-qcom.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
drivers/usb/dwc3/dwc3-qcom.c +6 -3
@@ -639,16 +639,19 @@ static int dwc3_qcom_of_register_core(st ret =of_platform_populate (np,NULL ,NULL , dev);if (ret) {dev_err (dev,"failed to register dwc3 core - %d\n" , ret); -return ret; + goto node_put; } qcom->dwc3 =of_find_device_by_node (dwc3_np);if (!qcom->dwc3) { + ret = -ENODEV ;dev_err (dev,"failed to get dwc3 platform device\n" ); -return -ENODEV ; } -return 0 ; +node_put: +of_node_put (dwc3_np); + +return ret; }static int dwc3_qcom_probe (struct platform_device *pdev)
[email protected]
maintainerPATCH 199/306 usb: dwc3: qcom: add URS Host support for sdm845 ACPI boot
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Shawn Guo <[email protected]>
commit c25c210f590e7a37eecd865d84f97d1f40e39786 upstream.
For sdm845 ACPI boot, the URS (USB Role Switch) node in ACPI DSDT table holds the memory resource, while interrupt resources reside in the child nodes USB0 and UFN0. It adds USB0 host support by probing URS node, creating platform device for USB0 node, and then retrieve interrupt resources from USB0 platform device.
--- drivers/usb/dwc3/dwc3-qcom.c | 59 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 3 deletions(-)
drivers/usb/dwc3/dwc3-qcom.c +56 -3
@@ -60,12 +60,14 @@ struct dwc3_acpi_pdata {int dp_hs_phy_irq_index;int dm_hs_phy_irq_index;int ss_phy_irq_index; +bool is_urs; };struct dwc3_qcom {struct device *dev;void __iomem *qscratch_base;struct platform_device *dwc3; +struct platform_device *urs_usb;struct clk **clks;int num_clocks;struct reset_control *resets;
@@ -429,13 +431,15 @@ static void dwc3_qcom_select_utmi_clk(ststatic int dwc3_qcom_get_irq (struct platform_device *pdev,const char *name,int num) { +struct dwc3_qcom *qcom =platform_get_drvdata (pdev); +struct platform_device *pdev_irq = qcom->urs_usb ? qcom->urs_usb : pdev;struct device_node *np = pdev->dev.of_node;int ret;if (np) - ret =platform_get_irq_byname (pdev, name); + ret =platform_get_irq_byname (pdev_irq, name);else - ret =platform_get_irq (pdev, num); + ret =platform_get_irq (pdev_irq, num);return ret; }
@@ -568,6 +572,8 @@ static int dwc3_qcom_acpi_register_core(struct dwc3_qcom *qcom =platform_get_drvdata (pdev);struct device *dev = &pdev->dev;struct resource *res, *child_res =NULL ; +struct platform_device *pdev_irq = qcom->urs_usb ? qcom->urs_usb : + pdev;int irq;int ret;
@@ -597,7 +603,7 @@ static int dwc3_qcom_acpi_register_core( child_res[0 ].end = child_res[0 ].start + qcom->acpi_pdata->dwc3_core_base_size; - irq =platform_get_irq (pdev,0 ); + irq =platform_get_irq (pdev_irq,0 ); child_res[1 ].flags =IORESOURCE_IRQ ; child_res[1 ].start = child_res[1 ].end = irq;
@@ -654,6 +660,33 @@ node_put:return ret; } +static struct platform_device * +dwc3_qcom_create_urs_usb_platdev (struct device *dev) +{ +struct fwnode_handle *fwh; +struct acpi_device *adev; +char name[8 ]; +int ret; +int id; + +/* Figure out device id */ + ret =sscanf (fwnode_get_name (dev->fwnode),"URS%d" , &id); +if (!ret) +return NULL ; + +/* Find the child using name */ +snprintf (name,sizeof (name),"USB%d" , id); + fwh =fwnode_get_named_child_node (dev->fwnode, name); +if (!fwh) +return NULL ; + + adev =to_acpi_device_node (fwh); +if (!adev) +return NULL ; + +return acpi_create_platform_device (adev,NULL ); +} +static int dwc3_qcom_probe (struct platform_device *pdev) {struct device_node *np = pdev->dev.of_node;
@@ -718,6 +751,14 @@ static int dwc3_qcom_probe(struct platfo qcom->acpi_pdata->qscratch_base_offset; parent_res->end = parent_res->start + qcom->acpi_pdata->qscratch_base_size; + +if (qcom->acpi_pdata->is_urs) { + qcom->urs_usb =dwc3_qcom_create_urs_usb_platdev (dev); +if (!qcom->urs_usb) { +dev_err (dev,"failed to create URS USB platdev\n" ); +return -ENODEV ; + } + } } qcom->qscratch_base =devm_ioremap_resource (dev, parent_res);
@@ -880,8 +921,20 @@ static const struct dwc3_acpi_pdata sdm8 .ss_phy_irq_index = 2 }; +static const struct dwc3_acpi_pdata sdm845_acpi_urs_pdata = { + .qscratch_base_offset =SDM845_QSCRATCH_BASE_OFFSET , + .qscratch_base_size =SDM845_QSCRATCH_SIZE , + .dwc3_core_base_size =SDM845_DWC3_CORE_SIZE , + .hs_phy_irq_index =1 , + .dp_hs_phy_irq_index =4 , + .dm_hs_phy_irq_index =3 , + .ss_phy_irq_index =2 , + .is_urs = true, +}; +static const struct acpi_device_id dwc3_qcom_acpi_match[] = { {"QCOM2430" , (unsigned long )&sdm845_acpi_pdata }, + {"QCOM0304" , (unsigned long )&sdm845_acpi_urs_pdata }, { }, };MODULE_DEVICE_TABLE (acpi, dwc3_qcom_acpi_match);
[email protected]
maintainerPATCH 200/306 usb: dwc3: qcom: add ACPI device id for sc8180x
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Shawn Guo <[email protected]>
commit 1edbff9c80ed32071fffa7dbaaea507fdb21ff2d upstream.
It enables USB Host support for sc8180x ACPI boot, both the standalone one and the one behind URS (USB Role Switch). And they share the the same dwc3_acpi_pdata with sdm845.
--- drivers/usb/dwc3/dwc3-qcom.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/usb/dwc3/dwc3-qcom.c +2 -0
@@ -935,6 +935,8 @@ static const struct dwc3_acpi_pdata sdm8static const struct acpi_device_id dwc3_qcom_acpi_match[] = { {"QCOM2430" , (unsigned long )&sdm845_acpi_pdata }, {"QCOM0304" , (unsigned long )&sdm845_acpi_urs_pdata }, + {"QCOM0497" , (unsigned long )&sdm845_acpi_urs_pdata }, + {"QCOM04A6" , (unsigned long )&sdm845_acpi_pdata }, { }, };MODULE_DEVICE_TABLE (acpi, dwc3_qcom_acpi_match);
[email protected]
maintainerPATCH 201/306 usb: dwc3: qcom: Honor wakeup enabled/disabled state
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Matthias Kaehlcke <[email protected]>
commit 2664deb0930643149d61cddbb66ada527ae180bd upstream.
The dwc3-qcom currently enables wakeup interrupts unconditionally when suspending, however this should not be done when wakeup is disabled (e.g. through the sysfs attribute power/wakeup). Only enable wakeup interrupts when device_may_wakeup() returns true.
--- drivers/usb/dwc3/dwc3-qcom.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/usb/dwc3/dwc3-qcom.c +5 -2
@@ -358,8 +358,10 @@ static int dwc3_qcom_suspend(struct dwc3if (ret)dev_warn (qcom->dev,"failed to disable interconnect: %d\n" , ret); +if (device_may_wakeup (qcom->dev)) +dwc3_qcom_enable_interrupts (qcom); + qcom->is_suspended = true; -dwc3_qcom_enable_interrupts (qcom);return 0 ; }
@@ -372,7 +374,8 @@ static int dwc3_qcom_resume(struct dwc3_if (!qcom->is_suspended)return 0 ; -dwc3_qcom_disable_interrupts (qcom); +if (device_may_wakeup (qcom->dev)) +dwc3_qcom_disable_interrupts (qcom);for (i =0 ; i < qcom->num_clocks; i++) { ret =clk_prepare_enable (qcom->clks[i]);
[email protected]
maintainerPATCH 202/306 USB: usblp: fix a hang in poll() if disconnected
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Pete Zaitcev <[email protected]>
commit 9de2c43acf37a17dc4c69ff78bb099b80fb74325 upstream.
Apparently an application that opens a device and calls select() on it, will hang if the decice is disconnected. It's a little surprising that we had this bug for 15 years, but apparently nobody ever uses select() with a printer: only write() and read(), and those work fine. Well, you can also select() with a timeout.
The fix is modeled after devio.c. A few other drivers check the condition first, then do not add the wait queue in case the device is disconnected. We doubt that's completely race-free. So, this patch adds the process first, then locks properly and checks for the disconnect.
--- drivers/usb/class/usblp.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
drivers/usb/class/usblp.c +12 -4
@@ -494,16 +494,24 @@ static int usblp_release(struct inode *i/* No kernel lock - fine */ static __poll_t usblp_poll (struct file *file,struct poll_table_struct *wait) { -__poll_t ret; +struct usblp *usblp = file->private_data; +__poll_t ret =0 ;unsigned long flags; -struct usblp *usblp = file->private_data;/* Should we check file->f_mode & FMODE_WRITE before poll_wait()? */ poll_wait (file, &usblp->rwait, wait);poll_wait (file, &usblp->wwait, wait); + +mutex_lock (&usblp->mut); +if (!usblp->present) + ret |=EPOLLHUP ; +mutex_unlock (&usblp->mut); +spin_lock_irqsave (&usblp->lock, flags); - ret = ((usblp->bidir && usblp->rcomplete) ?EPOLLIN |EPOLLRDNORM :0 ) | - ((usblp->no_paper || usblp->wcomplete) ?EPOLLOUT |EPOLLWRNORM :0 ); +if (usblp->bidir && usblp->rcomplete) + ret |=EPOLLIN |EPOLLRDNORM ; +if (usblp->no_paper || usblp->wcomplete) + ret |=EPOLLOUT |EPOLLWRNORM ;spin_unlock_irqrestore (&usblp->lock, flags);return ret; }
[email protected]
maintainerPATCH 203/306 usb: renesas_usbhs: Clear PIPECFG for re-enabling pipe with other EPNUM
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Yoshihiro Shimoda <[email protected]>
commit b1d25e6ee57c2605845595b6c61340d734253eb3 upstream.
According to the datasheet, this controller has a restriction which "set an endpoint number so that combinations of the DIR bit and the EPNUM bits do not overlap.". However, since the udc core driver is possible to assign a bulk pipe as an interrupt endpoint, an endpoint number may not match the pipe number. After that, when user rebinds another gadget driver, this driver broke the restriction because the driver didn't clear any configuration in usb_ep_disable().
Example:
# modprobe g_ncm Then, EP3 = pipe 3, EP4 = pipe 4, EP5 = pipe 6 # rmmod g_ncm # modprobe g_hid Then, EP3 = pipe 6, EP4 = pipe 7. So, pipe 3 and pipe 6 are set as EP3.
So, clear PIPECFG register in usbhs_pipe_free().
--- drivers/usb/renesas_usbhs/pipe.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/usb/renesas_usbhs/pipe.c +2 -0
@@ -746,6 +746,8 @@ struct usbhs_pipe *usbhs_pipe_malloc(strvoid usbhs_pipe_free (struct usbhs_pipe *pipe) { +usbhsp_pipe_select (pipe); +usbhsp_pipe_cfg_set (pipe,0xFFFF ,0 );usbhsp_put_pipe (pipe); }
[email protected]
maintainerPATCH 204/306 usb: xhci: do not perform Soft Retry for some xHCI hosts
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Stanislaw Gruszka <[email protected]>
commit a4a251f8c23518899d2078c320cf9ce2fa459c9f upstream.
On some systems rt2800usb and mt7601u devices are unable to operate since commit f8f80be501aa ("xhci: Use soft retry to recover faster from transaction errors")
Seems that some xHCI controllers can not perform Soft Retry correctly, affecting those devices.
To avoid the problem add xhci->quirks flag that restore pre soft retry xhci behaviour for affected xHCI controllers. Currently those are AMD_PROMONTORYA_4 and AMD_PROMONTORYA_2, since it was confirmed by the users: on those xHCI hosts issue happen and is gone after disabling Soft Retry.
[minor commit message rewording for checkpatch -Mathias]
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=202541
--- drivers/usb/host/xhci-pci.c | 5 +++++ drivers/usb/host/xhci-ring.c | 3 ++- drivers/usb/host/xhci.h | 1 + 3 files changed, 8 insertions(+), 1 deletion(-)
drivers/usb/host/xhci-pci.c +5 -0
@@ -295,6 +295,11 @@ static void xhci_pci_quirks(struct devic pdev->device == 0x9026) xhci->quirks |=XHCI_RESET_PLL_ON_DISCONNECT ; +if (pdev->vendor ==PCI_VENDOR_ID_AMD && + (pdev->device ==PCI_DEVICE_ID_AMD_PROMONTORYA_2 || + pdev->device ==PCI_DEVICE_ID_AMD_PROMONTORYA_4 )) + xhci->quirks |=XHCI_NO_SOFT_RETRY ; +if (xhci->quirks &XHCI_RESET_ON_RESUME )xhci_dbg_trace (xhci, trace_xhci_dbg_quirks,"QUIRK: Resetting on resume" );
drivers/usb/host/xhci-ring.c +2 -1
@@ -2307,7 +2307,8 @@ static int process_bulk_intr_td(struct x remaining =0 ;break ;case COMP_USB_TRANSACTION_ERROR : -if ((ep_ring->err_count++ >MAX_SOFT_RETRY ) || +if (xhci->quirks &XHCI_NO_SOFT_RETRY || + (ep_ring->err_count++ >MAX_SOFT_RETRY ) ||le32_to_cpu (slot_ctx->tt_info) &TT_SLOT )break ; *status =0 ;
drivers/usb/host/xhci.h +1 -0
@@ -1883,6 +1883,7 @@ struct xhci_hcd {#define XHCI_SKIP_PHY_INIT BIT_ULL(37)#define XHCI_DISABLE_SPARSE BIT_ULL(38)#define XHCI_SG_TRB_CACHE_SIZE_QUIRK BIT_ULL(39) +#define XHCI_NO_SOFT_RETRY BIT_ULL(40)unsigned int num_active_eps;unsigned int limit_active_eps;
[email protected]
maintainerPATCH 205/306 xhci: Improve detection of device initiated wake signal.
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Mathias Nyman <[email protected]>
commit 253f588c70f66184b1f3a9bbb428b49bbda73e80 upstream.
A xHC USB 3 port might miss the first wake signal from a USB 3 device if the port LFPS reveiver isn't enabled fast enough after xHC resume.
xHC host will anyway be resumed by a PME# signal, but will go back to suspend if no port activity is seen.
The device resends the U3 LFPS wake signal after a 100ms delay, but by then host is already suspended, starting all over from the beginning of this issue.
USB 3 specs say U3 wake LFPS signal is sent for max 10ms, then device needs to delay 100ms before resending the wake.
Don't suspend immediately if port activity isn't detected in resume. Instead add a retry. If there is no port activity then delay for 120ms, and re-check for port activity.
--- drivers/usb/host/xhci.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-)
drivers/usb/host/xhci.c +13 -3
@@ -1088,6 +1088,7 @@ int xhci_resume(struct xhci_hcd *xhci, bstruct usb_hcd *secondary_hcd;int retval =0 ;bool comp_timer_running = false; +bool pending_portevent = false;if (!hcd->state)return 0 ;
@@ -1226,13 +1227,22 @@ int xhci_resume(struct xhci_hcd *xhci, b done:if (retval ==0 ) { -/* Resume root hubs only when have pending events. */ -if (xhci_pending_portevent (xhci)) { +/* +* Resume roothubs only if there are pending events. +* USB 3 devices resend U3 LFPS wake after a 100ms delay if +* the first wake signalling failed, give it that chance. +*/ + pending_portevent =xhci_pending_portevent (xhci); +if (!pending_portevent) { +msleep (120 ); + pending_portevent =xhci_pending_portevent (xhci); + } + +if (pending_portevent) {usb_hcd_resume_root_hub (xhci->shared_hcd);usb_hcd_resume_root_hub (hcd); } } -/* * If system is subject to the Quirk, Compliance Mode Timer needs to * be re-initialized Always after a system resume. Ports are subject
[email protected]
maintainerPATCH 206/306 usb: xhci: Fix ASMedia ASM1042A and ASM3242 DMA addressing
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Forest Crossman <[email protected]>
commit b71c669ad8390dd1c866298319ff89fe68b45653 upstream.
I've confirmed that both the ASMedia ASM1042A and ASM3242 have the same problem as the ASM1142 and ASM2142/ASM3142, where they lose some of the upper bits of 64-bit DMA addresses. As with the other chips, this can cause problems on systems where the upper bits matter, and adding the XHCI_NO_64BIT_SUPPORT quirk completely fixes the issue.
--- drivers/usb/host/xhci-pci.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/usb/host/xhci-pci.c +6 -2
@@ -66,6 +66,7 @@#define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI 0x1142#define PCI_DEVICE_ID_ASMEDIA_1142_XHCI 0x1242#define PCI_DEVICE_ID_ASMEDIA_2142_XHCI 0x2142 +#define PCI_DEVICE_ID_ASMEDIA_3242_XHCI 0x3242static const char hcd_name[] ="xhci_hcd" ;
@@ -276,11 +277,14 @@ static void xhci_pci_quirks(struct devic pdev->device == PCI_DEVICE_ID_ASMEDIA_1042_XHCI) xhci->quirks |= XHCI_BROKEN_STREAMS;if (pdev->vendor ==PCI_VENDOR_ID_ASMEDIA && - pdev->device ==PCI_DEVICE_ID_ASMEDIA_1042A_XHCI ) + pdev->device ==PCI_DEVICE_ID_ASMEDIA_1042A_XHCI ) { xhci->quirks |=XHCI_TRUST_TX_LENGTH ; + xhci->quirks |=XHCI_NO_64BIT_SUPPORT ; + }if (pdev->vendor ==PCI_VENDOR_ID_ASMEDIA && (pdev->device ==PCI_DEVICE_ID_ASMEDIA_1142_XHCI || - pdev->device ==PCI_DEVICE_ID_ASMEDIA_2142_XHCI )) + pdev->device ==PCI_DEVICE_ID_ASMEDIA_2142_XHCI || + pdev->device ==PCI_DEVICE_ID_ASMEDIA_3242_XHCI )) xhci->quirks |=XHCI_NO_64BIT_SUPPORT ; if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
[email protected]
maintainerPATCH 207/306 xhci: Fix repeated xhci wake after suspend due to uncleared internal wake state
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Mathias Nyman <[email protected]>
commit d26c00e7276fc92b18c253d69e872f6b03832bad upstream.
If port terminations are detected in suspend, but link never reaches U0 then xHCI may have an internal uncleared wake state that will cause an immediate wake after suspend.
This wake state is normally cleared when driver clears the PORT_CSC bit, which is set after a device is enabled and in U0.
Write 1 to clear PORT_CSC for ports that don't have anything connected when suspending. This makes sure any pending internal wake states in xHCI are cleared.
--- drivers/usb/host/xhci.c | 62 +++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 32 deletions(-)
drivers/usb/host/xhci.c +30 -32
@@ -883,44 +883,42 @@ static void xhci_clear_command_ring(struxhci_set_cmd_ring_deq (xhci); } -static void xhci_disable_port_wake_on_bits (struct xhci_hcd *xhci) +/* +* Disable port wake bits if do_wakeup is not set. +* +* Also clear a possible internal port wake state left hanging for ports that +* detected termination but never successfully enumerated (trained to 0U). +* Internal wake causes immediate xHCI wake after suspend. PORT_CSC write done +* at enumeration clears this wake, force one here as well for unconnected ports +*/ + +static void xhci_disable_hub_port_wake (struct xhci_hcd *xhci, +struct xhci_hub *rhub, +bool do_wakeup) { -struct xhci_port **ports; -int port_index;unsigned long flags;u32 t1, t2, portsc; +int i;spin_lock_irqsave (&xhci->lock, flags); -/* disable usb3 ports Wake bits */ - port_index = xhci->usb3_rhub.num_ports; - ports = xhci->usb3_rhub.ports; -while (port_index--) { - t1 =readl (ports[port_index]->addr); - portsc = t1; - t1 =xhci_port_state_to_neutral (t1); - t2 = t1 & ~PORT_WAKE_BITS ; -if (t1 != t2) { -writel (t2, ports[port_index]->addr); -xhci_dbg (xhci,"disable wake bits port %d-%d, portsc: 0x%x, write: 0x%x\n" , - xhci->usb3_rhub.hcd->self.busnum, - port_index +1 , portsc, t2); - } - } +for (i =0 ; i < rhub->num_ports; i++) { + portsc =readl (rhub->ports[i]->addr); + t1 =xhci_port_state_to_neutral (portsc); + t2 = t1; + +/* clear wake bits if do_wake is not set */ +if (!do_wakeup) + t2 &= ~PORT_WAKE_BITS ; + +/* Don't touch csc bit if connected or connect change is set */ +if (!(portsc & (PORT_CSC |PORT_CONNECT ))) + t2 |=PORT_CSC ; -/* disable usb2 ports Wake bits */ - port_index = xhci->usb2_rhub.num_ports; - ports = xhci->usb2_rhub.ports; -while (port_index--) { - t1 =readl (ports[port_index]->addr); - portsc = t1; - t1 =xhci_port_state_to_neutral (t1); - t2 = t1 & ~PORT_WAKE_BITS ;if (t1 != t2) { -writel (t2, ports[port_index]->addr); -xhci_dbg (xhci,"disable wake bits port %d-%d, portsc: 0x%x, write: 0x%x\n" , - xhci->usb2_rhub.hcd->self.busnum, - port_index +1 , portsc, t2); +writel (t2, rhub->ports[i]->addr); +xhci_dbg (xhci,"config port %d-%d wake bits, portsc: 0x%x, write: 0x%x\n" , + rhub->hcd->self.busnum, i +1 , portsc, t2); } }spin_unlock_irqrestore (&xhci->lock, flags);
@@ -983,8 +981,8 @@ int xhci_suspend(struct xhci_hcd *xhci,return -EINVAL ;/* Clear root port wake on bits if wakeup not allowed. */ -if (!do_wakeup) -xhci_disable_port_wake_on_bits (xhci); +xhci_disable_hub_port_wake (xhci, &xhci->usb3_rhub, do_wakeup); +xhci_disable_hub_port_wake (xhci, &xhci->usb2_rhub, do_wakeup);if (!HCD_HW_ACCESSIBLE (hcd))return 0 ;
[email protected]
maintainerPATCH 208/306 USB: serial: io_edgeport: fix memory leak in edge_startup
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Pavel Skripkin <[email protected]>
commit cfdc67acc785e01a8719eeb7012709d245564701 upstream.
sysbot found memory leak in edge_startup().
The problem was that when an error was received from the usb_submit_urb(), nothing was cleaned up.
--- drivers/usb/serial/io_edgeport.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-)
drivers/usb/serial/io_edgeport.c +16 -10
@@ -3003,26 +3003,32 @@ static int edge_startup(struct usb_seria response = -ENODEV ; } -usb_free_urb (edge_serial->interrupt_read_urb); -kfree (edge_serial->interrupt_in_buffer); - -usb_free_urb (edge_serial->read_urb); -kfree (edge_serial->bulk_in_buffer); - -kfree (edge_serial); - -return response; + goto error; }/* start interrupt read for this edgeport this interrupt will * continue as long as the edgeport is connected */ response =usb_submit_urb (edge_serial->interrupt_read_urb,GFP_KERNEL ); -if (response) +if (response) {dev_err (ddev,"%s - Error %d submitting control urb\n" , __func__, response); + + goto error; + } }return response; + +error: +usb_free_urb (edge_serial->interrupt_read_urb); +kfree (edge_serial->interrupt_in_buffer); + +usb_free_urb (edge_serial->read_urb); +kfree (edge_serial->bulk_in_buffer); + +kfree (edge_serial); + +return response; }
[email protected]
maintainerPATCH 209/306 USB: serial: ch341: add new Product ID
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Niv Sardi <[email protected]>
commit 5563b3b6420362c8a1f468ca04afe6d5f0a8d0a3 upstream.
Add PID for CH340 that's found on cheap programmers.
The driver works flawlessly as soon as the new PID (0x9986) is added to it. These look like ANU232MI but ship with a ch341 inside. They have no special identifiers (mine only has the string "DB9D20130716" printed on the PCB and nothing identifiable on the packaging. The merchant i bought it from doesn't sell these anymore).
the lsusb -v output is:
Bus 001 Device 009: ID 9986:7523
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 255 Vendor Specific Class
bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 8 idVendor 0x9986 idProduct 0x7523 bcdDevice 2.54 iManufacturer 0 iProduct 0 iSerial 0 bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 0x0027
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0x80
(Bus Powered)
MaxPower 96mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 3
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 1
bInterfaceProtocol 2
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0020 1x 32 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x02 EP 2 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0020 1x 32 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 1
--- drivers/usb/serial/ch341.c | 1 + 1 file changed, 1 insertion(+)
drivers/usb/serial/ch341.c +1 -0
@@ -86,6 +86,7 @@ static const struct usb_device_id id_tab { USB_DEVICE(0x1a86, 0x7522) }, { USB_DEVICE(0x1a86, 0x7523) }, { USB_DEVICE(0x4348, 0x5523) }, + { USB_DEVICE(0x9986, 0x7523) }, { }, };MODULE_DEVICE_TABLE (usb, id_table);
[email protected]
maintainerPATCH 210/306 USB: serial: cp210x: add ID for Acuity Brands nLight Air Adapter
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Karan Singhal <[email protected]>
commit ca667a33207daeaf9c62b106815728718def60ec upstream.
IDs of nLight Air Adapter, Acuity Brands, Inc.:
vid: 10c4
pid: 88d8
--- drivers/usb/serial/cp210x.c | 1 + 1 file changed, 1 insertion(+)
drivers/usb/serial/cp210x.c +1 -0
@@ -146,6 +146,7 @@ static const struct usb_device_id id_tab { USB_DEVICE(0x10C4, 0x8857) }, /* CEL EM357 ZigBee USB Stick */ { USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */ { USB_DEVICE(0x10C4, 0x88A5) }, /* Planet Innovation Ingeni ZigBee USB Device */ + { USB_DEVICE(0x10C4, 0x88D8) }, /* Acuity Brands nLight Air Adapter */ { USB_DEVICE(0x10C4, 0x88FB) }, /* CESINEL MEDCAL STII Network Analyzer */ { USB_DEVICE(0x10C4, 0x8938) }, /* CESINEL MEDCAL S II Network Analyzer */ { USB_DEVICE(0x10C4, 0x8946) }, /* Ketra N1 Wireless Interface */
[email protected]
maintainerPATCH 211/306 USB: serial: cp210x: add some more GE USB IDs
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Sebastian Reichel <[email protected]>
commit 42213a0190b535093a604945db05a4225bf43885 upstream.
GE CS1000 has some more custom USB IDs for CP2102N; add them to the driver to have working auto-probing.
--- drivers/usb/serial/cp210x.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/usb/serial/cp210x.c +2 -0
@@ -203,6 +203,8 @@ static const struct usb_device_id id_tab { USB_DEVICE(0x1901, 0x0194) }, /* GE Healthcare Remote Alarm Box */ { USB_DEVICE(0x1901, 0x0195) }, /* GE B850/B650/B450 CP2104 DP UART interface */ { USB_DEVICE(0x1901, 0x0196) }, /* GE B850 CP2105 DP UART interface */ + { USB_DEVICE(0x1901, 0x0197) }, /* GE CS1000 Display serial interface */ + { USB_DEVICE(0x1901, 0x0198) }, /* GE CS1000 M.2 Key E serial interface */ { USB_DEVICE(0x199B, 0xBA30) }, /* LORD WSDA-200-USB */ { USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */ { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */
[email protected]
maintainerPATCH 212/306 usbip: fix stub_dev to check for stream socket
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Shuah Khan <[email protected]>
commit 47ccc8fc2c9c94558b27b6f9e2582df32d29e6e8 upstream.
Fix usbip_sockfd_store() to validate the passed in file descriptor is a stream socket. If the file descriptor passed was a SOCK_DGRAM socket, sock_recvmsg() can't detect end of stream.
--- drivers/usb/usbip/stub_dev.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
drivers/usb/usbip/stub_dev.c +11 -1
@@ -69,8 +69,16 @@ static ssize_t usbip_sockfd_store(struct } socket =sockfd_lookup (sockfd, &err); -if (!socket) +if (!socket) { +dev_err (dev,"failed to lookup sock" ); goto err; + } + +if (socket->type !=SOCK_STREAM ) { +dev_err (dev,"Expecting SOCK_STREAM - found %d" , + socket->type); + goto sock_err; + } sdev->ud.tcp_socket = socket; sdev->ud.sockfd = sockfd;
@@ -100,6 +108,8 @@ static ssize_t usbip_sockfd_store(structreturn count; +sock_err: +sockfd_put (socket); err:spin_unlock_irq (&sdev->ud.lock);return -EINVAL ;
[email protected]
maintainerPATCH 213/306 usbip: fix vhci_hcd to check for stream socket
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Shuah Khan <[email protected]>
commit f55a0571690c4aae03180e001522538c0927432f upstream.
Fix attach_store() to validate the passed in file descriptor is a stream socket. If the file descriptor passed was a SOCK_DGRAM socket, sock_recvmsg() can't detect end of stream.
--- drivers/usb/usbip/vhci_sysfs.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
drivers/usb/usbip/vhci_sysfs.c +9 -1
@@ -349,8 +349,16 @@ static ssize_t attach_store(struct devic/* Extract socket from fd. */ socket =sockfd_lookup (sockfd, &err); -if (!socket) +if (!socket) { +dev_err (dev,"failed to lookup sock" );return -EINVAL ; + } +if (socket->type !=SOCK_STREAM ) { +dev_err (dev,"Expecting SOCK_STREAM - found %d" , + socket->type); +sockfd_put (socket); +return -EINVAL ; + }/* now need lock until setting vdev status as used */
[email protected]
maintainerPATCH 214/306 usbip: fix vudc to check for stream socket
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Shuah Khan <[email protected]>
commit 6801854be94fe8819b3894979875ea31482f5658 upstream.
Fix usbip_sockfd_store() to validate the passed in file descriptor is a stream socket. If the file descriptor passed was a SOCK_DGRAM socket, sock_recvmsg() can't detect end of stream.
--- drivers/usb/usbip/vudc_sysfs.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/usb/usbip/vudc_sysfs.c +9 -0
@@ -138,6 +138,13 @@ static ssize_t usbip_sockfd_store(struct goto unlock_ud; } +if (socket->type !=SOCK_STREAM ) { +dev_err (dev,"Expecting SOCK_STREAM - found %d" , + socket->type); + ret = -EINVAL ; + goto sock_err; + } + udc->ud.tcp_socket = socket;spin_unlock_irq (&udc->ud.lock);
@@ -177,6 +184,8 @@ static ssize_t usbip_sockfd_store(structreturn count; +sock_err: +sockfd_put (socket); unlock_ud:spin_unlock_irq (&udc->ud.lock); unlock:
[email protected]
maintainerPATCH 215/306 usbip: fix stub_dev usbip_sockfd_store() races leading to gpf
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Shuah Khan <[email protected]>
commit 9380afd6df70e24eacbdbde33afc6a3950965d22 upstream.
usbip_sockfd_store() is invoked when user requests attach (import) detach (unimport) usb device from usbip host. vhci_hcd sends import request and usbip_sockfd_store() exports the device if it is free for export.
Export and unexport are governed by local state and shared state
- Shared state (usbip device status, sockfd) - sockfd and Device status are used to determine if stub should be brought up or shut down.
- Local state (tcp_socket, rx and tx thread task_struct ptrs) A valid tcp_socket controls rx and tx thread operations while the device is in exported state.
- While the device is exported, device status is marked used and socket, sockfd, and thread pointers are valid.
Export sequence (stub-up) includes validating the socket and creating receive (rx) and transmit (tx) threads to talk to the client to provide access to the exported device. rx and tx threads depends on local and shared state to be correct and in sync.
Unexport (stub-down) sequence shuts the socket down and stops the rx and tx threads. Stub-down sequence relies on local and shared states to be in sync.
There are races in updating the local and shared status in the current stub-up sequence resulting in crashes. These stem from starting rx and tx threads before local and global state is updated correctly to be in sync.
1. Doesn't handle kthread_create() error and saves invalid ptr in local state that drives rx and tx threads.
2. Updates tcp_socket and sockfd, starts stub_rx and stub_tx threads before updating usbip_device status to SDEV_ST_USED. This opens up a race condition between the threads and usbip_sockfd_store() stub up and down handling.
Fix the above problems:
- Stop using kthread_get_run() macro to create/start threads.
- Create threads and get task struct reference.
- Add kthread_create() failure handling and bail out.
- Hold usbip_device lock to update local and shared states after creating rx and tx threads.
- Update usbip_device status to SDEV_ST_USED.
- Update usbip_device tcp_socket, sockfd, tcp_rx, and tcp_tx
- Start threads after usbip_device (tcp_socket, sockfd, tcp_rx, tcp_tx, and status) is complete.
Credit goes to syzbot and Tetsuo Handa for finding and root-causing the kthread_get_run() improper error handling problem and others. This is a hard problem to find and debug since the races aren't seen in a normal case. Fuzzing forces the race window to be small enough for the kthread_get_run() error path bug and starting threads before updating the local and shared state bug in the stub-up sequence.
Tested with syzbot reproducer:
- https://syzkaller.appspot.com/text?tag=ReproC&x=14801034d00000
--- drivers/usb/usbip/stub_dev.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-)
drivers/usb/usbip/stub_dev.c +25 -7
@@ -46,6 +46,8 @@ static ssize_t usbip_sockfd_store(structint sockfd =0 ;struct socket *socket;int rv; +struct task_struct *tcp_rx =NULL ; +struct task_struct *tcp_tx =NULL ;if (!sdev) {dev_err (dev,"sdev is null\n" );
@@ -80,20 +82,36 @@ static ssize_t usbip_sockfd_store(struct goto sock_err; } - sdev->ud.tcp_socket = socket; - sdev->ud.sockfd = sockfd; - +/* unlock and create threads and get tasks */ spin_unlock_irq (&sdev->ud.lock); + tcp_rx =kthread_create (stub_rx_loop, &sdev->ud,"stub_rx" ); +if (IS_ERR (tcp_rx)) { +sockfd_put (socket); +return -EINVAL ; + } + tcp_tx =kthread_create (stub_tx_loop, &sdev->ud,"stub_tx" ); +if (IS_ERR (tcp_tx)) { +kthread_stop (tcp_rx); +sockfd_put (socket); +return -EINVAL ; + } - sdev->ud.tcp_rx =kthread_get_run (stub_rx_loop, &sdev->ud, -"stub_rx" ); - sdev->ud.tcp_tx =kthread_get_run (stub_tx_loop, &sdev->ud, -"stub_tx" ); +/* get task structs now */ +get_task_struct (tcp_rx); +get_task_struct (tcp_tx); +/* lock and update sdev->ud state */ spin_lock_irq (&sdev->ud.lock); + sdev->ud.tcp_socket = socket; + sdev->ud.sockfd = sockfd; + sdev->ud.tcp_rx = tcp_rx; + sdev->ud.tcp_tx = tcp_tx; sdev->ud.status =SDEV_ST_USED ;spin_unlock_irq (&sdev->ud.lock); +wake_up_process (sdev->ud.tcp_rx); +wake_up_process (sdev->ud.tcp_tx); + }else {dev_info (dev,"stub down\n" );
[email protected]
maintainerPATCH 216/306 usbip: fix vhci_hcd attach_store() races leading to gpf
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Shuah Khan <[email protected]>
commit 718ad9693e3656120064b715fe931f43a6201e67 upstream.
attach_store() is invoked when user requests import (attach) a device from usbip host.
Attach and detach are governed by local state and shared state
- Shared state (usbip device status) - Device status is used to manage the attach and detach operations on import-able devices.
- Local state (tcp_socket, rx and tx thread task_struct ptrs) A valid tcp_socket controls rx and tx thread operations while the device is in exported state.
- Device has to be in the right state to be attached and detached.
Attach sequence includes validating the socket and creating receive (rx) and transmit (tx) threads to talk to the host to get access to the imported device. rx and tx threads depends on local and shared state to be correct and in sync.
Detach sequence shuts the socket down and stops the rx and tx threads. Detach sequence relies on local and shared states to be in sync.
There are races in updating the local and shared status in the current attach sequence resulting in crashes. These stem from starting rx and tx threads before local and global state is updated correctly to be in sync.
1. Doesn't handle kthread_create() error and saves invalid ptr in local state that drives rx and tx threads.
2. Updates tcp_socket and sockfd, starts stub_rx and stub_tx threads before updating usbip_device status to VDEV_ST_NOTASSIGNED. This opens up a race condition between the threads, port connect, and detach handling.
Fix the above problems:
- Stop using kthread_get_run() macro to create/start threads.
- Create threads and get task struct reference.
- Add kthread_create() failure handling and bail out.
- Hold vhci and usbip_device locks to update local and shared states after creating rx and tx threads.
- Update usbip_device status to VDEV_ST_NOTASSIGNED.
- Update usbip_device tcp_socket, sockfd, tcp_rx, and tcp_tx
- Start threads after usbip_device (tcp_socket, sockfd, tcp_rx, tcp_tx, and status) is complete.
Credit goes to syzbot and Tetsuo Handa for finding and root-causing the kthread_get_run() improper error handling problem and others. This is hard problem to find and debug since the races aren't seen in a normal case. Fuzzing forces the race window to be small enough for the kthread_get_run() error path bug and starting threads before updating the local and shared state bug in the attach sequence.
- Update usbip_device tcp_rx and tcp_tx pointers holding vhci and usbip_device locks.
Tested with syzbot reproducer:
- https://syzkaller.appspot.com/text?tag=ReproC&x=14801034d00000
--- drivers/usb/usbip/vhci_sysfs.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-)
drivers/usb/usbip/vhci_sysfs.c +25 -4
@@ -312,6 +312,8 @@ static ssize_t attach_store(struct devicstruct vhci *vhci;int err;unsigned long flags; +struct task_struct *tcp_rx =NULL ; +struct task_struct *tcp_tx =NULL ;/* * @rhport: port number of vhci_hcd
@@ -360,9 +362,24 @@ static ssize_t attach_store(struct devicreturn -EINVAL ; } -/* now need lock until setting vdev status as used */ +/* create threads before locking */ + tcp_rx =kthread_create (vhci_rx_loop, &vdev->ud,"vhci_rx" ); +if (IS_ERR (tcp_rx)) { +sockfd_put (socket); +return -EINVAL ; + } + tcp_tx =kthread_create (vhci_tx_loop, &vdev->ud,"vhci_tx" ); +if (IS_ERR (tcp_tx)) { +kthread_stop (tcp_rx); +sockfd_put (socket); +return -EINVAL ; + } + +/* get task structs now */ +get_task_struct (tcp_rx); +get_task_struct (tcp_tx); -/* begin a lock */ +/* now begin lock until setting vdev status set */ spin_lock_irqsave (&vhci->lock, flags);spin_lock (&vdev->ud.lock);
@@ -372,6 +389,8 @@ static ssize_t attach_store(struct devicspin_unlock_irqrestore (&vhci->lock, flags);sockfd_put (socket); +kthread_stop_put (tcp_rx); +kthread_stop_put (tcp_tx);dev_err (dev,"port %d already used\n" , rhport);/*
@@ -390,14 +409,16 @@ static ssize_t attach_store(struct devic vdev->speed = speed; vdev->ud.sockfd = sockfd; vdev->ud.tcp_socket = socket; + vdev->ud.tcp_rx = tcp_rx; + vdev->ud.tcp_tx = tcp_tx; vdev->ud.status =VDEV_ST_NOTASSIGNED ;spin_unlock (&vdev->ud.lock);spin_unlock_irqrestore (&vhci->lock, flags);/* end the lock */ - vdev->ud.tcp_rx =kthread_get_run (vhci_rx_loop, &vdev->ud,"vhci_rx" ); - vdev->ud.tcp_tx =kthread_get_run (vhci_tx_loop, &vdev->ud,"vhci_tx" ); +wake_up_process (vdev->ud.tcp_rx); +wake_up_process (vdev->ud.tcp_tx);rh_port_connect (vdev, speed);
[email protected]
maintainerPATCH 217/306 usbip: fix vudc usbip_sockfd_store races leading to gpf
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Shuah Khan <[email protected]>
commit 46613c9dfa964c0c60b5385dbdf5aaa18be52a9c upstream.
usbip_sockfd_store() is invoked when user requests attach (import) detach (unimport) usb gadget device from usbip host. vhci_hcd sends import request and usbip_sockfd_store() exports the device if it is free for export.
Export and unexport are governed by local state and shared state
- Shared state (usbip device status, sockfd) - sockfd and Device status are used to determine if stub should be brought up or shut down. Device status is shared between host and client.
- Local state (tcp_socket, rx and tx thread task_struct ptrs) A valid tcp_socket controls rx and tx thread operations while the device is in exported state.
- While the device is exported, device status is marked used and socket, sockfd, and thread pointers are valid.
Export sequence (stub-up) includes validating the socket and creating receive (rx) and transmit (tx) threads to talk to the client to provide access to the exported device. rx and tx threads depends on local and shared state to be correct and in sync.
Unexport (stub-down) sequence shuts the socket down and stops the rx and tx threads. Stub-down sequence relies on local and shared states to be in sync.
There are races in updating the local and shared status in the current stub-up sequence resulting in crashes. These stem from starting rx and tx threads before local and global state is updated correctly to be in sync.
1. Doesn't handle kthread_create() error and saves invalid ptr in local state that drives rx and tx threads.
2. Updates tcp_socket and sockfd, starts stub_rx and stub_tx threads before updating usbip_device status to SDEV_ST_USED. This opens up a race condition between the threads and usbip_sockfd_store() stub up and down handling.
Fix the above problems:
- Stop using kthread_get_run() macro to create/start threads.
- Create threads and get task struct reference.
- Add kthread_create() failure handling and bail out.
- Hold usbip_device lock to update local and shared states after creating rx and tx threads.
- Update usbip_device status to SDEV_ST_USED.
- Update usbip_device tcp_socket, sockfd, tcp_rx, and tcp_tx
- Start threads after usbip_device (tcp_socket, sockfd, tcp_rx, tcp_tx, and status) is complete.
Credit goes to syzbot and Tetsuo Handa for finding and root-causing the kthread_get_run() improper error handling problem and others. This is a hard problem to find and debug since the races aren't seen in a normal case. Fuzzing forces the race window to be small enough for the kthread_get_run() error path bug and starting threads before updating the local and shared state bug in the stub-up sequence.
--- drivers/usb/usbip/vudc_sysfs.c | 42 +++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-)
drivers/usb/usbip/vudc_sysfs.c +34 -8
@@ -90,8 +90,9 @@ unlock: } static BIN_ATTR_RO(dev_desc, sizeof(struct usb_device_descriptor)); -static ssize_t usbip_sockfd_store (struct device *dev,struct device_attribute *attr, -const char *in,size_t count) +static ssize_t usbip_sockfd_store (struct device *dev, +struct device_attribute *attr, +const char *in,size_t count) {struct vudc *udc = (struct vudc *)dev_get_drvdata (dev);int rv;
@@ -100,6 +101,8 @@ static ssize_t usbip_sockfd_store(structstruct socket *socket;unsigned long flags;int ret; +struct task_struct *tcp_rx =NULL ; +struct task_struct *tcp_tx =NULL ; rv =kstrtoint (in,0 , &sockfd);if (rv !=0 )
@@ -145,24 +148,47 @@ static ssize_t usbip_sockfd_store(struct goto sock_err; } - udc->ud.tcp_socket = socket; - +/* unlock and create threads and get tasks */ spin_unlock_irq (&udc->ud.lock);spin_unlock_irqrestore (&udc->lock, flags); - udc->ud.tcp_rx =kthread_get_run (&v_rx_loop, - &udc->ud,"vudc_rx" ); - udc->ud.tcp_tx =kthread_get_run (&v_tx_loop, - &udc->ud,"vudc_tx" ); + tcp_rx =kthread_create (&v_rx_loop, &udc->ud,"vudc_rx" ); +if (IS_ERR (tcp_rx)) { +sockfd_put (socket); +return -EINVAL ; + } + tcp_tx =kthread_create (&v_tx_loop, &udc->ud,"vudc_tx" ); +if (IS_ERR (tcp_tx)) { +kthread_stop (tcp_rx); +sockfd_put (socket); +return -EINVAL ; + } + +/* get task structs now */ +get_task_struct (tcp_rx); +get_task_struct (tcp_tx); +/* lock and update udc->ud state */ spin_lock_irqsave (&udc->lock, flags);spin_lock_irq (&udc->ud.lock); + + udc->ud.tcp_socket = socket; + udc->ud.tcp_rx = tcp_rx; + udc->ud.tcp_rx = tcp_tx; udc->ud.status =SDEV_ST_USED ; +spin_unlock_irq (&udc->ud.lock);ktime_get_ts64 (&udc->start_time);v_start_timer (udc); udc->connected =1 ; + +spin_unlock_irqrestore (&udc->lock, flags); + +wake_up_process (udc->ud.tcp_rx); +wake_up_process (udc->ud.tcp_tx); +return count; + }else {if (!udc->connected) {dev_err (dev,"Device not connected" );
[email protected]
maintainerPATCH 218/306 Revert "serial: max310x: rework RX interrupt handling"
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Alexander Shiyan <[email protected]>
commit 2334de198fed3da72e9785ecdd691d101aa96e77 upstream.
This reverts commit fce3c5c1a2d9cd888f2987662ce17c0c651916b2.
FIFO is triggered 4 intervals after receiving a byte, it's good when we don't care about the time of reception, but are only interested in the presence of any activity on the line. Unfortunately, this method is not suitable for all tasks, for example, the RS-485 protocol will not work properly, since the state machine must track the request-response time and after the timeout expires, a decision is made that the device on the line is not responding.
--- drivers/tty/serial/max310x.c | 29 +++++------------------------ 1 file changed, 5 insertions(+), 24 deletions(-)
drivers/tty/serial/max310x.c +5 -24
@@ -1056,9 +1056,9 @@ static int max310x_startup(struct uart_pmax310x_port_update (port,MAX310X_MODE1_REG ,MAX310X_MODE1_TRNSCVCTRL_BIT ,0 ); -/* Reset FIFOs */ -max310x_port_write (port,MAX310X_MODE2_REG , -MAX310X_MODE2_FIFORST_BIT ); +/* Configure MODE2 register & Reset FIFOs*/ + val =MAX310X_MODE2_RXEMPTINV_BIT |MAX310X_MODE2_FIFORST_BIT ; +max310x_port_write (port,MAX310X_MODE2_REG , val);max310x_port_update (port,MAX310X_MODE2_REG ,MAX310X_MODE2_FIFORST_BIT ,0 );
@@ -1086,27 +1086,8 @@ static int max310x_startup(struct uart_p/* Clear IRQ status register */ max310x_port_read (port,MAX310X_IRQSTS_REG ); -/* -* Let's ask for an interrupt after a timeout equivalent to -* the receiving time of 4 characters after the last character -* has been received. -*/ -max310x_port_write (port,MAX310X_RXTO_REG ,4 ); - -/* -* Make sure we also get RX interrupts when the RX FIFO is -* filling up quickly, so get an interrupt when half of the RX -* FIFO has been filled in. -*/ -max310x_port_write (port,MAX310X_FIFOTRIGLVL_REG , -MAX310X_FIFOTRIGLVL_RX (MAX310X_FIFO_SIZE /2 )); - -/* Enable RX timeout interrupt in LSR */ -max310x_port_write (port,MAX310X_LSR_IRQEN_REG , -MAX310X_LSR_RXTO_BIT ); - -/* Enable LSR, RX FIFO trigger, CTS change interrupts */ - val =MAX310X_IRQ_LSR_BIT |MAX310X_IRQ_RXFIFO_BIT |MAX310X_IRQ_TXEMPTY_BIT ; +/* Enable RX, TX, CTS change interrupts */ + val =MAX310X_IRQ_RXEMPTY_BIT |MAX310X_IRQ_TXEMPTY_BIT ;max310x_port_write (port,MAX310X_IRQEN_REG , val |MAX310X_IRQ_CTS_BIT );return 0 ;
[email protected]
maintainerPATCH 219/306 misc/pvpanic: Export module FDT device table
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Shile Zhang <[email protected]>
commit 65527a51c66f4edfa28602643d7dd4fa366eb826 upstream.
Export the module FDT device table to ensure the FDT compatible strings are listed in the module alias. This help the pvpanic driver can be loaded on boot automatically not only the ACPI device, but also the FDT device.
--- drivers/misc/pvpanic.c | 1 + 1 file changed, 1 insertion(+)
drivers/misc/pvpanic.c +1 -0
@@ -92,6 +92,7 @@ static const struct of_device_id pvpanic { .compatible = "qemu,pvpanic-mmio", }, {} }; +MODULE_DEVICE_TABLE (of, pvpanic_mmio_match);static const struct acpi_device_id pvpanic_device_ids[] = { {"QEMU0001" ,0 },
[email protected]
maintainerPATCH 220/306 misc: fastrpc: restrict user apps from sending kernel RPC messages
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Dmitry Baryshkov <[email protected]>
commit 20c40794eb85ea29852d7bc37c55713802a543d6 upstream.
Verify that user applications are not using the kernel RPC message handle to restrict them from directly attaching to guest OS on the remote subsystem. This is a port of CVE-2019-2308 fix.
--- drivers/misc/fastrpc.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/misc/fastrpc.c +5 -0
@@ -950,6 +950,11 @@ static int fastrpc_internal_invoke(strucif (!fl->cctx->rpdev)return -EPIPE ; +if (handle ==FASTRPC_INIT_HANDLE && !kernel) { +dev_warn_ratelimited (fl->sctx->dev,"user app trying to send a kernel RPC message (%d)\n" , handle); +return -EPERM ; + } + ctx =fastrpc_context_alloc (fl, kernel, sc, args);if (IS_ERR (ctx))return PTR_ERR (ctx);
[email protected]
maintainerPATCH 221/306 staging: rtl8192u: fix ->ssid overflow in r8192_wx_set_scan()
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Dan Carpenter <[email protected]>
commit 87107518d7a93fec6cdb2559588862afeee800fb upstream.
We need to cap len at IW_ESSID_MAX_SIZE (32) to avoid memory corruption. This can be controlled by the user via the ioctl.
--- drivers/staging/rtl8192u/r8192U_wx.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/staging/rtl8192u/r8192U_wx.c +4 -2
@@ -331,8 +331,10 @@ static int r8192_wx_set_scan(struct net_struct iw_scan_req *req = (struct iw_scan_req *)b;if (req->essid_len) { - ieee->current_network.ssid_len = req->essid_len; -memcpy (ieee->current_network.ssid, req->essid, req->essid_len); +int len =min_t (int, req->essid_len,IW_ESSID_MAX_SIZE ); + + ieee->current_network.ssid_len = len; +memcpy (ieee->current_network.ssid, req->essid, len); } }
[email protected]
maintainerPATCH 222/306 staging: rtl8188eu: prevent ->ssid overflow in rtw_wx_set_scan()
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Dan Carpenter <[email protected]>
commit 74b6b20df8cfe90ada777d621b54c32e69e27cd7 upstream.
This code has a check to prevent read overflow but it needs another check to prevent writing beyond the end of the ->ssid[] array.
--- drivers/staging/rtl8188eu/os_dep/ioctl_linux.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +4 -2
@@ -1133,9 +1133,11 @@ static int rtw_wx_set_scan(struct net_debreak ; } sec_len = *(pos++); len -=1 ; -if (sec_len >0 && sec_len <= len) { +if (sec_len >0 && + sec_len <= len && + sec_len <=32 ) { ssid[ssid_index].ssid_length = sec_len; -memcpy (ssid[ssid_index].ssid, pos, ssid[ssid_index].ssid_length); +memcpy (ssid[ssid_index].ssid, pos, sec_len); ssid_index++; } pos += sec_len;
[email protected]
maintainerPATCH 223/306 staging: rtl8712: unterminated string leads to read overflow
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Dan Carpenter <[email protected]>
commit d660f4f42ccea50262c6ee90c8e7ad19a69fb225 upstream.
The memdup_user() function does not necessarily return a NUL terminated string so this can lead to a read overflow. Switch from memdup_user() to strndup_user() to fix this bug.
--- drivers/staging/rtl8712/rtl871x_ioctl_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/staging/rtl8712/rtl871x_ioctl_linux.c +1 -1
@@ -924,7 +924,7 @@ static int r871x_wx_set_priv(struct net_struct iw_point *dwrq = (struct iw_point *)awrq; len = dwrq->length; - ext =memdup_user (dwrq->pointer, len); + ext =strndup_user (dwrq->pointer, len);if (IS_ERR (ext))return PTR_ERR (ext);
[email protected]
maintainerPATCH 224/306 staging: rtl8188eu: fix potential memory corruption in rtw_check_beacon_data()
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Dan Carpenter <[email protected]>
commit d4ac640322b06095128a5c45ba4a1e80929fe7f3 upstream.
The "ie_len" is a value in the 1-255 range that comes from the user. We have to cap it to ensure that it's not too large or it could lead to memory corruption.
--- drivers/staging/rtl8188eu/core/rtw_ap.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/staging/rtl8188eu/core/rtw_ap.c +5 -0
@@ -791,6 +791,7 @@ int rtw_check_beacon_data(struct adapter p =rtw_get_ie (ie + _BEACON_IE_OFFSET_,WLAN_EID_SSID , &ie_len, pbss_network->ie_length - _BEACON_IE_OFFSET_);if (p && ie_len >0 ) { + ie_len =min_t (int, ie_len,sizeof (pbss_network->ssid.ssid));memset (&pbss_network->ssid,0 ,sizeof (struct ndis_802_11_ssid ));memcpy (pbss_network->ssid.ssid, p +2 , ie_len); pbss_network->ssid.ssid_length = ie_len;
@@ -811,6 +812,7 @@ int rtw_check_beacon_data(struct adapter p =rtw_get_ie (ie + _BEACON_IE_OFFSET_,WLAN_EID_SUPP_RATES , &ie_len, pbss_network->ie_length - _BEACON_IE_OFFSET_);if (p) { + ie_len =min_t (int, ie_len,NDIS_802_11_LENGTH_RATES_EX );memcpy (supportRate, p +2 , ie_len); supportRateNum = ie_len; }
@@ -819,6 +821,8 @@ int rtw_check_beacon_data(struct adapter p =rtw_get_ie (ie + _BEACON_IE_OFFSET_,WLAN_EID_EXT_SUPP_RATES , &ie_len, pbss_network->ie_length - _BEACON_IE_OFFSET_);if (p) { + ie_len =min_t (int, ie_len, +NDIS_802_11_LENGTH_RATES_EX - supportRateNum);memcpy (supportRate + supportRateNum, p +2 , ie_len); supportRateNum += ie_len; }
@@ -934,6 +938,7 @@ int rtw_check_beacon_data(struct adapter pht_cap->mcs.rx_mask[0 ] =0xff ; pht_cap->mcs.rx_mask[1 ] =0x0 ; + ie_len =min_t (int, ie_len,sizeof (pmlmepriv->htpriv.ht_cap));memcpy (&pmlmepriv->htpriv.ht_cap, p +2 , ie_len); }
[email protected]
maintainerPATCH 225/306 staging: ks7010: prevent buffer overflow in ks_wlan_set_scan()
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Dan Carpenter <[email protected]>
commit e163b9823a0b08c3bb8dc4f5b4b5c221c24ec3e5 upstream.
The user can specify a "req->essid_len" of up to 255 but if it's over IW_ESSID_MAX_SIZE (32) that can lead to memory corruption.
--- drivers/staging/ks7010/ks_wlan_net.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/staging/ks7010/ks_wlan_net.c +4 -2
@@ -1120,6 +1120,7 @@ static int ks_wlan_set_scan(struct net_d {struct ks_wlan_private *priv =netdev_priv (dev);struct iw_scan_req *req =NULL ; +int len;if (priv->sleep_mode ==SLP_SLEEP )return -EPERM ;
@@ -1129,8 +1130,9 @@ static int ks_wlan_set_scan(struct net_dif (wrqu->data.length ==sizeof (struct iw_scan_req ) && wrqu->data.flags &IW_SCAN_THIS_ESSID ) { req = (struct iw_scan_req *)extra; - priv->scan_ssid_len = req->essid_len; -memcpy (priv->scan_ssid, req->essid, priv->scan_ssid_len); + len =min_t (int, req->essid_len,IW_ESSID_MAX_SIZE ); + priv->scan_ssid_len = len; +memcpy (priv->scan_ssid, req->essid, len); }else { priv->scan_ssid_len =0 ; }
[email protected]
maintainerPATCH 226/306 staging: rtl8712: Fix possible buffer overflow in r8712_sitesurvey_cmd
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Lee Gibson <[email protected]>
commit b93c1e3981af19527beee1c10a2bef67a228c48c upstream.
Function r8712_sitesurvey_cmd calls memcpy without checking the length. A user could control that length and trigger a buffer overflow. Fix by checking the length is within the maximum allowed size.
--- drivers/staging/rtl8712/rtl871x_cmd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/staging/rtl8712/rtl871x_cmd.c +4 -2
@@ -192,8 +192,10 @@ u8 r8712_sitesurvey_cmd(struct _adapter psurveyPara->ss_ssidlen =0 ;memset (psurveyPara->ss_ssid,0 ,IW_ESSID_MAX_SIZE +1 );if (pssid && pssid->SsidLength) { -memcpy (psurveyPara->ss_ssid, pssid->Ssid, pssid->SsidLength); - psurveyPara->ss_ssidlen =cpu_to_le32 (pssid->SsidLength); +int len =min_t (int, pssid->SsidLength,IW_ESSID_MAX_SIZE ); + +memcpy (psurveyPara->ss_ssid, pssid->Ssid, len); + psurveyPara->ss_ssidlen =cpu_to_le32 (len); }set_fwstate (pmlmepriv, _FW_UNDER_SURVEY);r8712_enqueue_cmd (pcmdpriv, ph2c);
[email protected]
maintainerPATCH 227/306 staging: rtl8192e: Fix possible buffer overflow in _rtl92e_wx_set_scan
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Lee Gibson <[email protected]>
commit 8687bf9ef9551bcf93897e33364d121667b1aadf upstream.
Function _rtl92e_wx_set_scan calls memcpy without checking the length. A user could control that length and trigger a buffer overflow. Fix by checking the length is within the maximum allowed size.
--- drivers/staging/rtl8192e/rtl8192e/rtl_wx.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/staging/rtl8192e/rtl8192e/rtl_wx.c +4 -3
@@ -406,9 +406,10 @@ static int _rtl92e_wx_set_scan(struct nestruct iw_scan_req *req = (struct iw_scan_req *)b;if (req->essid_len) { - ieee->current_network.ssid_len = req->essid_len; -memcpy (ieee->current_network.ssid, req->essid, - req->essid_len); +int len =min_t (int, req->essid_len,IW_ESSID_MAX_SIZE ); + + ieee->current_network.ssid_len = len; +memcpy (ieee->current_network.ssid, req->essid, len); } }
[email protected]
maintainerPATCH 228/306 staging: comedi: addi_apci_1032: Fix endian problem for COS sample
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Ian Abbott <[email protected]>
commit 25317f428a78fde71b2bf3f24d05850f08a73a52 upstream.
The Change-Of-State (COS) subdevice supports Comedi asynchronous commands to read 16-bit change-of-state values. However, the interrupt handler is calling comedi_buf_write_samples() with the address of a 32-bit integer &s->state. On bigendian architectures, it will copy 2 bytes from the wrong end of the 32-bit integer. Fix it by transferring the value via a 16-bit integer.
--- drivers/staging/comedi/drivers/addi_apci_1032.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/staging/comedi/drivers/addi_apci_1032.c +3 -1
@@ -260,6 +260,7 @@ static irqreturn_t apci1032_interrupt(instruct apci1032_private *devpriv = dev->private;struct comedi_subdevice *s = dev->read_subdev;unsigned int ctrl; +unsigned short val;/* check interrupt is from this device */ if ((inl(devpriv->amcc_iobase + AMCC_OP_REG_INTCSR) &
@@ -275,7 +276,8 @@ static irqreturn_t apci1032_interrupt(inoutl (ctrl & ~APCI1032_CTRL_INT_ENA , dev->iobase +APCI1032_CTRL_REG ); s->state =inl (dev->iobase +APCI1032_STATUS_REG ) &0xffff ; -comedi_buf_write_samples (s, &s->state,1 ); + val = s->state; +comedi_buf_write_samples (s, &val,1 );comedi_handle_events (dev, s);/* enable the interrupt */
[email protected]
maintainerPATCH 229/306 staging: comedi: addi_apci_1500: Fix endian problem for command sample
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Ian Abbott <[email protected]>
commit ac0bbf55ed3be75fde1f8907e91ecd2fd589bde3 upstream.
The digital input subdevice supports Comedi asynchronous commands that read interrupt status information. This uses 16-bit Comedi samples (of which only the bottom 8 bits contain status information). However, the interrupt handler is calling comedi_buf_write_samples() with the address of a 32-bit variable unsigned int status. On a bigendian machine, this will copy 2 bytes from the wrong end of the variable. Fix it by changing the type of the variable to unsigned short.
--- drivers/staging/comedi/drivers/addi_apci_1500.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
drivers/staging/comedi/drivers/addi_apci_1500.c +9 -9
@@ -208,7 +208,7 @@ static irqreturn_t apci1500_interrupt(instruct comedi_device *dev = d;struct apci1500_private *devpriv = dev->private;struct comedi_subdevice *s = dev->read_subdev; -unsigned int status =0 ; +unsigned short status =0 ;unsigned int val; val =inl (devpriv->amcc +AMCC_OP_REG_INTCSR );
@@ -238,14 +238,14 @@ static irqreturn_t apci1500_interrupt(in* * Mask Meaning * ---------- ------------------------------------------ -* 0x00000001 Event 1 has occurred -* 0x00000010 Event 2 has occurred -* 0x00000100 Counter/timer 1 has run down (not implemented) -* 0x00001000 Counter/timer 2 has run down (not implemented) -* 0x00010000 Counter 3 has run down (not implemented) -* 0x00100000 Watchdog has run down (not implemented) -* 0x01000000 Voltage error -* 0x10000000 Short-circuit error +* 0b00000001 Event 1 has occurred +* 0b00000010 Event 2 has occurred +* 0b00000100 Counter/timer 1 has run down (not implemented) +* 0b00001000 Counter/timer 2 has run down (not implemented) +* 0b00010000 Counter 3 has run down (not implemented) +* 0b00100000 Watchdog has run down (not implemented) +* 0b01000000 Voltage error +* 0b10000000 Short-circuit error */ comedi_buf_write_samples (s, &status,1 );comedi_handle_events (dev, s);
[email protected]
maintainerPATCH 230/306 staging: comedi: adv_pci1710: Fix endian problem for AI command data
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Ian Abbott <[email protected]>
commit b2e78630f733a76508b53ba680528ca39c890e82 upstream.
The analog input subdevice supports Comedi asynchronous commands that use Comedi's 16-bit sample format. However, the calls to comedi_buf_write_samples() are passing the address of a 32-bit integer variable. On bigendian machines, this will copy 2 bytes from the wrong end of the 32-bit value. Fix it by changing the type of the variables holding the sample value to unsigned short. The type of the val parameter of pci1710_ai_read_sample() is changed to unsigned short * accordingly. The type of the val variable in pci1710_ai_insn_read() is also changed to unsigned short since its address is passed to pci1710_ai_read_sample().
--- drivers/staging/comedi/drivers/adv_pci1710.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/staging/comedi/drivers/adv_pci1710.c +5 -5
@@ -300,11 +300,11 @@ static int pci1710_ai_eoc(struct comedi_static int pci1710_ai_read_sample (struct comedi_device *dev,struct comedi_subdevice *s,unsigned int cur_chan, -unsigned int *val) +unsigned short *val) {const struct boardtype *board = dev->board_ptr;struct pci1710_private *devpriv = dev->private; -unsigned int sample; +unsigned short sample;unsigned int chan; sample =inw (dev->iobase +PCI171X_AD_DATA_REG );
@@ -345,7 +345,7 @@ static int pci1710_ai_insn_read(struct cpci1710_ai_setup_chanlist (dev, s, &insn->chanspec,1 ,1 );for (i =0 ; i < insn->n; i++) { -unsigned int val; +unsigned short val;/* start conversion */ outw (0 , dev->iobase +PCI171X_SOFTTRG_REG );
@@ -395,7 +395,7 @@ static void pci1710_handle_every_sample( {struct comedi_cmd *cmd = &s->async->cmd;unsigned int status; -unsigned int val; +unsigned short val;int ret; status =inw (dev->iobase +PCI171X_STATUS_REG );
@@ -455,7 +455,7 @@ static void pci1710_handle_fifo(struct c }for (i =0 ; i < devpriv->max_samples; i++) { -unsigned int val; +unsigned short val;int ret; ret =pci1710_ai_read_sample (dev, s, s->async->cur_chan, &val);
[email protected]
maintainerPATCH 231/306 staging: comedi: das6402: Fix endian problem for AI command data
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Ian Abbott <[email protected]>
commit 1c0f20b78781b9ca50dc3ecfd396d0db5b141890 upstream.
The analog input subdevice supports Comedi asynchronous commands that use Comedi's 16-bit sample format. However, the call to comedi_buf_write_samples() is passing the address of a 32-bit integer variable. On bigendian machines, this will copy 2 bytes from the wrong end of the 32-bit value. Fix it by changing the type of the variable holding the sample value to unsigned short.
--- drivers/staging/comedi/drivers/das6402.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/staging/comedi/drivers/das6402.c +1 -1
@@ -186,7 +186,7 @@ static irqreturn_t das6402_interrupt(intif (status &DAS6402_STATUS_FFULL ) { async->events |=COMEDI_CB_OVERFLOW ; }else if (status &DAS6402_STATUS_FFNE ) { -unsigned int val; +unsigned short val; val =das6402_ai_read_sample (dev, s);comedi_buf_write_samples (s, &val,1 );
[email protected]
maintainerPATCH 232/306 staging: comedi: das800: Fix endian problem for AI command data
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Ian Abbott <[email protected]>
commit 459b1e8c8fe97fcba0bd1b623471713dce2c5eaf upstream.
The analog input subdevice supports Comedi asynchronous commands that use Comedi's 16-bit sample format. However, the call to comedi_buf_write_samples() is passing the address of a 32-bit integer variable. On bigendian machines, this will copy 2 bytes from the wrong end of the 32-bit value. Fix it by changing the type of the variable holding the sample value to unsigned short.
--- drivers/staging/comedi/drivers/das800.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/staging/comedi/drivers/das800.c +1 -1
@@ -427,7 +427,7 @@ static irqreturn_t das800_interrupt(intstruct comedi_cmd *cmd;unsigned long irq_flags;unsigned int status; -unsigned int val; +unsigned short val;bool fifo_empty;bool fifo_overflow;int i;
[email protected]
maintainerPATCH 233/306 staging: comedi: dmm32at: Fix endian problem for AI command data
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Ian Abbott <[email protected]>
commit 54999c0d94b3c26625f896f8e3460bc029821578 upstream.
The analog input subdevice supports Comedi asynchronous commands that use Comedi's 16-bit sample format. However, the call to comedi_buf_write_samples() is passing the address of a 32-bit integer variable. On bigendian machines, this will copy 2 bytes from the wrong end of the 32-bit value. Fix it by changing the type of the variable holding the sample value to unsigned short.
[Note: the bug was introduced in commit 1700529b24cc ("staging: comedi:
dmm32at: use comedi_buf_write_samples()") but the patch applies better to the later (but in the same kernel release) commit 0c0eadadcbe6e ("staging: comedi: dmm32at: introduce dmm32_ai_get_sample()").]
--- drivers/staging/comedi/drivers/dmm32at.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/staging/comedi/drivers/dmm32at.c +1 -1
@@ -404,7 +404,7 @@ static irqreturn_t dmm32at_isr(int irq, {struct comedi_device *dev = d;unsigned char intstat; -unsigned int val; +unsigned short val;int i;if (!dev->attached) {
[email protected]
maintainerPATCH 234/306 staging: comedi: me4000: Fix endian problem for AI command data
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Ian Abbott <[email protected]>
commit b39dfcced399d31e7c4b7341693b18e01c8f655e upstream.
The analog input subdevice supports Comedi asynchronous commands that use Comedi's 16-bit sample format. However, the calls to comedi_buf_write_samples() are passing the address of a 32-bit integer variable. On bigendian machines, this will copy 2 bytes from the wrong end of the 32-bit value. Fix it by changing the type of the variable holding the sample value to unsigned short.
--- drivers/staging/comedi/drivers/me4000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/staging/comedi/drivers/me4000.c +1 -1
@@ -924,7 +924,7 @@ static irqreturn_t me4000_ai_isr(int irqstruct comedi_subdevice *s = dev->read_subdev;int i;int c =0 ; -unsigned int lval; +unsigned short lval;if (!dev->attached)return IRQ_NONE ;
[email protected]
maintainerPATCH 235/306 staging: comedi: pcl711: Fix endian problem for AI command data
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Ian Abbott <[email protected]>
commit a084303a645896e834883f2c5170d044410dfdb3 upstream.
The analog input subdevice supports Comedi asynchronous commands that use Comedi's 16-bit sample format. However, the call to comedi_buf_write_samples() is passing the address of a 32-bit integer variable. On bigendian machines, this will copy 2 bytes from the wrong end of the 32-bit value. Fix it by changing the type of the variable holding the sample value to unsigned short.
--- drivers/staging/comedi/drivers/pcl711.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/staging/comedi/drivers/pcl711.c +1 -1
@@ -184,7 +184,7 @@ static irqreturn_t pcl711_interrupt(intstruct comedi_device *dev = d;struct comedi_subdevice *s = dev->read_subdev;struct comedi_cmd *cmd = &s->async->cmd; -unsigned int data; +unsigned short data;if (!dev->attached) {dev_err (dev->class_dev,"spurious interrupt\n" );
[email protected]
maintainerPATCH 236/306 staging: comedi: pcl818: Fix endian problem for AI command data
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Ian Abbott <[email protected]>
commit 148e34fd33d53740642db523724226de14ee5281 upstream.
The analog input subdevice supports Comedi asynchronous commands that use Comedi's 16-bit sample format. However, the call to comedi_buf_write_samples() is passing the address of a 32-bit integer parameter. On bigendian machines, this will copy 2 bytes from the wrong end of the 32-bit value. Fix it by changing the type of the parameter holding the sample value to unsigned short.
[Note: the bug was introduced in commit edf4537bcbf5 ("staging: comedi:
pcl818: use comedi_buf_write_samples()") but the patch applies better to commit d615416de615 ("staging: comedi: pcl818: introduce pcl818_ai_write_sample()").]
--- drivers/staging/comedi/drivers/pcl818.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/staging/comedi/drivers/pcl818.c +1 -1
@@ -423,7 +423,7 @@ static int pcl818_ai_eoc(struct comedi_dstatic bool pcl818_ai_write_sample (struct comedi_device *dev,struct comedi_subdevice *s, -unsigned int chan,unsigned int val) +unsigned int chan,unsigned short val) {struct pcl818_private *devpriv = dev->private;struct comedi_cmd *cmd = &s->async->cmd;
[email protected]
maintainerPATCH 237/306 mlxsw: spectrum_router: Ignore routes using a deleted nexthop object
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Ido Schimmel <[email protected]>
[ Upstream commit dc860b88ce0a7ed9a048d5042cbb175daf60b657 ]
Routes are currently processed from a workqueue whereas nexthop objects are processed in system call context. This can result in the driver not finding a suitable nexthop group for a route and issuing a warning [1].
Fix this by ignoring such routes earlier in the process. The subsequent deletion notification will be ignored as well.
[1]
WARNING: CPU: 2 PID: 7754 at drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c:4853 mlxsw_sp_router_fib_event_work+0x1112/0x1e00 [mlxsw_spectrum] [...] CPU: 2 PID: 7754 Comm: kworker/u8:0 Not tainted 5.11.0-rc6-cq-20210207-1 #16 Hardware name: Mellanox Technologies Ltd. MSN2100/SA001390, BIOS 5.6.5 05/24/2018 Workqueue: mlxsw_core_ordered mlxsw_sp_router_fib_event_work [mlxsw_spectrum] RIP: 0010:mlxsw_sp_router_fib_event_work+0x1112/0x1e00 [mlxsw_spectrum]
--- drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +7 -0
@@ -5861,6 +5861,10 @@ mlxsw_sp_router_fib4_replace(struct mlxsw_sp *mlxsw_sp,if (mlxsw_sp->router->aborted)return 0 ; +if (fen_info->fi->nh && + !mlxsw_sp_nexthop_obj_group_lookup (mlxsw_sp, fen_info->fi->nh->id)) +return 0 ; + fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, fen_info->tb_id, &fen_info->dst, sizeof(fen_info->dst), fen_info->dst_len,
@@ -6511,6 +6515,9 @@ static int mlxsw_sp_router_fib6_replace(struct mlxsw_sp *mlxsw_sp,if (mlxsw_sp_fib6_rt_should_ignore (rt))return 0 ; +if (rt->nh && !mlxsw_sp_nexthop_obj_group_lookup (mlxsw_sp, rt->nh->id)) +return 0 ; + fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, rt->fib6_table->tb6_id, &rt->fib6_dst.addr, sizeof(rt->fib6_dst.addr),
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 238/306 net: phy: ti: take into account all possible interrupt sources
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Ioana Ciornei <[email protected]>
[ Upstream commit 73f476aa1975bae6a792b340f5b26ffcfba869a6 ]
The previous implementation of .handle_interrupt() did not take into account the fact that all the interrupt status registers should be acknowledged since multiple interrupt sources could be asserted.
Fix this by reading all the status registers before exiting with IRQ_NONE or triggering the PHY state machine.
--- drivers/net/phy/dp83822.c | 9 +++++---- drivers/net/phy/dp83tc811.c | 11 ++++++----- 2 files changed, 11 insertions(+), 9 deletions(-)
drivers/net/phy/dp83822.c +5 -4
@@ -290,6 +290,7 @@ static int dp83822_config_intr(struct phy_device *phydev)static irqreturn_t dp83822_handle_interrupt (struct phy_device *phydev) { +bool trigger_machine = false;int irq_status;/* The MISR1 and MISR2 registers are holding the interrupt status in
@@ -305,7 +306,7 @@ static irqreturn_t dp83822_handle_interrupt(struct phy_device *phydev)return IRQ_NONE ; }if (irq_status & ((irq_status &GENMASK (7 ,0 )) <<8 )) - goto trigger_machine; + trigger_machine = true; irq_status =phy_read (phydev,MII_DP83822_MISR2 );if (irq_status <0 ) {
@@ -313,11 +314,11 @@ static irqreturn_t dp83822_handle_interrupt(struct phy_device *phydev)return IRQ_NONE ; }if (irq_status & ((irq_status &GENMASK (7 ,0 )) <<8 )) - goto trigger_machine; + trigger_machine = true; -return IRQ_NONE ; +if (!trigger_machine) +return IRQ_NONE ; -trigger_machine:phy_trigger_machine (phydev);return IRQ_HANDLED ;
drivers/net/phy/dp83tc811.c +6 -5
@@ -264,6 +264,7 @@ static int dp83811_config_intr(struct phy_device *phydev)static irqreturn_t dp83811_handle_interrupt (struct phy_device *phydev) { +bool trigger_machine = false;int irq_status;/* The INT_STAT registers 1, 2 and 3 are holding the interrupt status
@@ -279,7 +280,7 @@ static irqreturn_t dp83811_handle_interrupt(struct phy_device *phydev)return IRQ_NONE ; }if (irq_status & ((irq_status &GENMASK (7 ,0 )) <<8 )) - goto trigger_machine; + trigger_machine = true; irq_status =phy_read (phydev,MII_DP83811_INT_STAT2 );if (irq_status <0 ) {
@@ -287,7 +288,7 @@ static irqreturn_t dp83811_handle_interrupt(struct phy_device *phydev)return IRQ_NONE ; }if (irq_status & ((irq_status &GENMASK (7 ,0 )) <<8 )) - goto trigger_machine; + trigger_machine = true; irq_status =phy_read (phydev,MII_DP83811_INT_STAT3 );if (irq_status <0 ) {
@@ -295,11 +296,11 @@ static irqreturn_t dp83811_handle_interrupt(struct phy_device *phydev)return IRQ_NONE ; }if (irq_status & ((irq_status &GENMASK (7 ,0 )) <<8 )) - goto trigger_machine; + trigger_machine = true; -return IRQ_NONE ; +if (!trigger_machine) +return IRQ_NONE ; -trigger_machine:phy_trigger_machine (phydev);return IRQ_HANDLED ;
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 239/306 sh_eth: fix TRSCER mask for R7S72100
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Sergey Shtylyov <[email protected]>
[ Upstream commit 75be7fb7f978202c4c3a1a713af4485afb2ff5f6 ]
According to the RZ/A1H Group, RZ/A1M Group User's Manual: Hardware, Rev. 4.00, the TRSCER register has bit 9 reserved, hence we can't use the driver's default TRSCER mask. Add the explicit initializer for sh_eth_cpu_data::trscer_err_mask for R7S72100.
--- drivers/net/ethernet/renesas/sh_eth.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/ethernet/renesas/sh_eth.c +2 -0
@@ -560,6 +560,8 @@ static struct sh_eth_cpu_data r7s72100_data = { EESR_TDE, .fdr_value = 0x0000070f, + .trscer_err_mask = DESC_I_RINT8 | DESC_I_RINT5, + .no_psr = 1, .apr = 1, .mpr = 1,
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 240/306 powerpc/sstep: Fix VSX instruction emulation
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Jordan Niethe <[email protected]>
[ Upstream commit 5c88a17e15795226b56d83f579cbb9b7a4864f79 ]
Commit af99da74333b ("powerpc/sstep: Support VSX vector paired storage access instructions") added loading and storing 32 word long data into adjacent VSRs. However the calculation used to determine if two VSRs needed to be loaded/stored inadvertently prevented the load/storing taking place for instructions with a data length less than 16 words.
This causes the emulation to not function correctly, which can be seen by the alignment_handler selftest:
$ ./alignment_handler
[snip]
test: test_alignment_handler_vsx_207
tags: git_version:powerpc-5.12-1-0-g82d2c16b350f
VSX: 2.07B
Doing lxsspx: PASSED
Doing lxsiwax: FAILED: Wrong Data
Doing lxsiwzx: PASSED
Doing stxsspx: PASSED
Doing stxsiwx: PASSED
failure: test_alignment_handler_vsx_207
test: test_alignment_handler_vsx_300
tags: git_version:powerpc-5.12-1-0-g82d2c16b350f
VSX: 3.00B
Doing lxsd: PASSED
Doing lxsibzx: PASSED
Doing lxsihzx: PASSED
Doing lxssp: FAILED: Wrong Data
Doing lxv: PASSED
Doing lxvb16x: PASSED
Doing lxvh8x: PASSED
Doing lxvx: PASSED
Doing lxvwsx: FAILED: Wrong Data
Doing lxvl: PASSED
Doing lxvll: PASSED
Doing stxsd: PASSED
Doing stxsibx: PASSED
Doing stxsihx: PASSED
Doing stxssp: PASSED
Doing stxv: PASSED
Doing stxvb16x: PASSED
Doing stxvh8x: PASSED
Doing stxvx: PASSED
Doing stxvl: PASSED
Doing stxvll: PASSED
failure: test_alignment_handler_vsx_300
[snip]Fix this by making sure all VSX instruction emulation correctly load/store from the VSRs.
--- arch/powerpc/lib/sstep.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/powerpc/lib/sstep.c +2 -2
@@ -904,7 +904,7 @@ static nokprobe_inline int do_vsx_load(struct instruction_op *op,if (!address_ok (regs, ea, size) ||copy_mem_in (mem, ea, size, regs))return -EFAULT ; - nr_vsx_regs = size /sizeof (__vector128); + nr_vsx_regs =max (1ul , size /sizeof (__vector128));emulate_vsx_load (op, buf, mem, cross_endian);preempt_disable ();if (reg <32 ) {
@@ -951,7 +951,7 @@ static nokprobe_inline int do_vsx_store(struct instruction_op *op,if (!address_ok (regs, ea, size))return -EFAULT ; - nr_vsx_regs = size /sizeof (__vector128); + nr_vsx_regs =max (1ul , size /sizeof (__vector128));preempt_disable ();if (reg <32 ) {/* FP regs + extensions */
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 241/306 net: macb: Add default usrio config to default gem config
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Atish Patra <[email protected]>
[ Upstream commit b12422362ce947098ac420ac3c975fc006af4c02 ]
There is no usrio config defined for default gem config leading to a kernel panic devices that don't define a data. This issue can be reprdouced with microchip polar fire soc where compatible string is defined as "cdns,macb".
--- drivers/net/ethernet/cadence/macb_main.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
drivers/net/ethernet/cadence/macb_main.c +8 -7
@@ -3950,6 +3950,13 @@ static int macb_init(struct platform_device *pdev)return 0 ; } +static const struct macb_usrio_config macb_default_usrio = { + .mii =MACB_BIT (MII ), + .rmii =MACB_BIT (RMII ), + .rgmii =GEM_BIT (RGMII ), + .refclk =MACB_BIT (CLKEN ), +}; +#if defined(CONFIG_OF )/* 1518 rounded up */ #define AT91ETHER_MAX_RBUFF_SZ 0x600
@@ -4435,13 +4442,6 @@ static int fu540_c000_init(struct platform_device *pdev)return macb_init (pdev); } -static const struct macb_usrio_config macb_default_usrio = { - .mii =MACB_BIT (MII ), - .rmii =MACB_BIT (RMII ), - .rgmii =GEM_BIT (RGMII ), - .refclk =MACB_BIT (CLKEN ), -}; -static const struct macb_usrio_config sama7g5_usrio = { .mii =0 , .rmii =1 ,
@@ -4590,6 +4590,7 @@ static const struct macb_config default_gem_config = { .dma_burst_length = 16, .clk_init = macb_clk_init, .init = macb_init, + .usrio = &macb_default_usrio, .jumbo_max_len = 10240, };
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 242/306 cpufreq: qcom-hw: fix dereferencing freed memory data
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Shawn Guo <[email protected]>
[ Upstream commit 02fc409540303801994d076fcdb7064bd634dbf3 ]
Commit 67fc209b527d ("cpufreq: qcom-hw: drop devm_xxx() calls from init/exit hooks") introduces an issue of dereferencing freed memory 'data'. Fix it.
--- drivers/cpufreq/qcom-cpufreq-hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/cpufreq/qcom-cpufreq-hw.c +1 -1
@@ -368,7 +368,7 @@ static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy) error:kfree (data); unmap_base: -iounmap (data->base); +iounmap (base); release_region:release_mem_region (res->start,resource_size (res));return ret;
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 243/306 cpufreq: qcom-hw: Fix return value check in qcom_cpufreq_hw_cpu_init()
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Wei Yongjun <[email protected]>
[ Upstream commit 536eb97abeba857126ad055de5923fa592acef25 ]
In case of error, the function ioremap() returns NULL pointer not ERR_PTR(). The IS_ERR() test in the return value check should be replaced with NULL test.
--- drivers/cpufreq/qcom-cpufreq-hw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/cpufreq/qcom-cpufreq-hw.c +2 -2
@@ -317,9 +317,9 @@ static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy) } base =ioremap (res->start,resource_size (res)); -if (IS_ERR (base)) { +if (!base) {dev_err (dev,"failed to map resource %pR\n" , res); - ret =PTR_ERR (base); + ret = -ENOMEM ; goto release_region; }
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 244/306 arm64/mm: Fix pfn_valid() for ZONE_DEVICE based memory
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Anshuman Khandual <[email protected]>
[ Upstream commit eeb0753ba27b26f609e61f9950b14f1b934fe429 ]
pfn_valid() validates a pfn but basically it checks for a valid struct page backing for that pfn. It should always return positive for memory ranges backed with struct page mapping. But currently pfn_valid() fails for all ZONE_DEVICE based memory types even though they have struct page mapping.
pfn_valid() asserts that there is a memblock entry for a given pfn without MEMBLOCK_NOMAP flag being set. The problem with ZONE_DEVICE based memory is that they do not have memblock entries. Hence memblock_is_map_memory() will invariably fail via memblock_search() for a ZONE_DEVICE based address. This eventually fails pfn_valid() which is wrong. memblock_is_map_memory() needs to be skipped for such memory ranges. As ZONE_DEVICE memory gets hotplugged into the system via memremap_pages() called from a driver, their respective memory sections will not have SECTION_IS_EARLY set.
Normal hotplug memory will never have MEMBLOCK_NOMAP set in their memblock regions. Because the flag MEMBLOCK_NOMAP was specifically designed and set for firmware reserved memory regions. memblock_is_map_memory() can just be skipped as its always going to be positive and that will be an optimization for the normal hotplug memory. Like ZONE_DEVICE based memory, all normal hotplugged memory too will not have SECTION_IS_EARLY set for their sections
Skipping memblock_is_map_memory() for all non early memory sections would fix pfn_valid() problem for ZONE_DEVICE based memory and also improve its performance for normal hotplug memory as well.
--- arch/arm64/mm/init.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
arch/arm64/mm/init.c +12 -0
@@ -230,6 +230,18 @@ int pfn_valid(unsigned long pfn)if (!valid_section (__pfn_to_section (pfn)))return 0 ; + +/* +* ZONE_DEVICE memory does not have the memblock entries. +* memblock_is_map_memory() check for ZONE_DEVICE based +* addresses will always fail. Even the normal hotplugged +* memory will never have MEMBLOCK_NOMAP flag set in their +* memblock entries. Skip memblock search for all non early +* memory sections covering all of hotplug memory including +* both normal and ZONE_DEVICE based. +*/ +if (!early_section (__pfn_to_section (pfn))) +return pfn_section_valid (__pfn_to_section (pfn), pfn);#endif return memblock_is_map_memory (addr); }
Signature · 9 lines
2.30.1 _______________________________________________ linux-arm-kernel mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
[email protected]
maintainerPATCH 245/306 SUNRPC: Set memalloc_nofs_save() for sync tasks
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Benjamin Coddington <[email protected]>
[ Upstream commit f0940f4b3284a00f38a5d42e6067c2aaa20e1f2e ]
We could recurse into NFS doing memory reclaim while sending a sync task, which might result in a deadlock. Set memalloc_nofs_save for sync task execution.
--- net/sunrpc/sched.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
net/sunrpc/sched.c +4 -1
@@ -963,8 +963,11 @@ void rpc_execute(struct rpc_task *task)rpc_set_active (task);rpc_make_runnable (rpciod_workqueue, task); -if (!is_async) +if (!is_async) { +unsigned int pflags =memalloc_nofs_save ();__rpc_execute (task); +memalloc_nofs_restore (pflags); + } }static void rpc_async_schedule (struct work_struct *work)
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 246/306 NFS: Dont revalidate the directory permissions on a lookup failure
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Trond Myklebust <[email protected]>
[ Upstream commit 82e7ca1334ab16e2e04fafded1cab9dfcdc11b40 ]
There should be no reason to expect the directory permissions to change just because the directory contents changed or a negative lookup timed out. So let's avoid doing a full call to nfs_mark_for_revalidate() in that case.
Furthermore, if this is a negative dentry, and we haven't actually done a new lookup, then we have no reason yet to believe the directory has changed at all. So let's remove the gratuitous directory inode invalidation altogether when called from nfs_lookup_revalidate_negative().
--- fs/nfs/dir.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-)
fs/nfs/dir.c +17 -3
@@ -1401,6 +1401,15 @@ int nfs_lookup_verify_inode(struct inode *inode, unsigned int flags) goto out; } +static void nfs_mark_dir_for_revalidate (struct inode *inode) +{ +struct nfs_inode *nfsi =NFS_I (inode); + +spin_lock (&inode->i_lock); + nfsi->cache_validity |=NFS_INO_REVAL_PAGECACHE ; +spin_unlock (&inode->i_lock); +} +/* * We judge how long we want to trust negative * dentries by looking at the parent inode mtime.
@@ -1435,7 +1444,6 @@ nfs_lookup_revalidate_done(struct inode *dir, struct dentry *dentry, __func__, dentry);return 1 ;case 0 : -nfs_mark_for_revalidate (dir);if (inode &&S_ISDIR (inode->i_mode)) {/* Purge readdir caches. */ nfs_zap_caches (inode);
@@ -1525,6 +1533,13 @@ nfs_lookup_revalidate_dentry(struct inode *dir, struct dentry *dentry,nfs_free_fattr (fattr);nfs_free_fhandle (fhandle);nfs4_label_free (label); + +/* +* If the lookup failed despite the dentry change attribute being +* a match, then we should revalidate the directory cache. +*/ +if (!ret &&nfs_verify_change_attribute (dir, dentry->d_time)) +nfs_mark_dir_for_revalidate (dir);return nfs_lookup_revalidate_done (dir, dentry, inode, ret); }
@@ -1567,7 +1582,7 @@ nfs_do_lookup_revalidate(struct inode *dir, struct dentry *dentry, error =nfs_lookup_verify_inode (inode, flags);if (error) {if (error == -ESTALE ) -nfs_zap_caches (dir); +nfs_mark_dir_for_revalidate (dir); goto out_bad; }nfs_advise_use_readdirplus (dir);
@@ -2064,7 +2079,6 @@ nfs_add_or_obtain(struct dentry *dentry, struct nfs_fh *fhandle,dput (parent);return d; out_error: -nfs_mark_for_revalidate (dir); d =ERR_PTR (error); goto out; }
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 247/306 NFS: Dont gratuitously clear the inode cache when lookup failed
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Trond Myklebust <[email protected]>
[ Upstream commit 47397915ede0192235474b145ebcd81b37b03624 ]
The fact that the lookup revalidation failed, does not mean that the inode contents have changed.
--- fs/nfs/dir.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-)
fs/nfs/dir.c +8 -12
@@ -1444,18 +1444,14 @@ nfs_lookup_revalidate_done(struct inode *dir, struct dentry *dentry, __func__, dentry);return 1 ;case 0 : -if (inode &&S_ISDIR (inode->i_mode)) { -/* Purge readdir caches. */ -nfs_zap_caches (inode); -/* -* We can't d_drop the root of a disconnected tree: -* its d_hash is on the s_anon list and d_drop() would hide -* it from shrink_dcache_for_unmount(), leading to busy -* inodes on unmount and further oopses. -*/ -if (IS_ROOT (dentry)) -return 1 ; - } +/* +* We can't d_drop the root of a disconnected tree: +* its d_hash is on the s_anon list and d_drop() would hide +* it from shrink_dcache_for_unmount(), leading to busy +* inodes on unmount and further oopses. +*/ +if (inode &&IS_ROOT (dentry)) +return 1 ;dfprintk (LOOKUPCACHE ,"NFS: %s(%pd2) is invalid\n" , __func__, dentry);return 0 ;
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 248/306 NFSv4.2: fix return value of _nfs4_get_security_label()
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Ondrej Mosnacek <[email protected]>
[ Upstream commit 53cb245454df5b13d7063162afd7a785aed6ebf2 ]
An xattr 'get' handler is expected to return the length of the value on success, yet _nfs4_get_security_label() (and consequently also nfs4_xattr_get_nfs4_label(), which is used as an xattr handler) returns just 0 on success.
Fix this by returning label.len instead, which contains the length of the result.
--- fs/nfs/nfs4proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nfs/nfs4proc.c +1 -1
@@ -5972,7 +5972,7 @@ static int _nfs4_get_security_label(struct inode *inode, void *buf,return ret;if (!(fattr.valid &NFS_ATTR_FATTR_V4_SECURITY_LABEL ))return -ENOENT ; -return 0 ; +return label.len; } static int nfs4_get_security_label(struct inode *inode, void *buf,
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 249/306 block: rsxx: fix error return code of rsxx_pci_probe()
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Jia-Ju Bai <[email protected]>
[ Upstream commit df66617bfe87487190a60783d26175b65d2502ce ]
When create_singlethread_workqueue returns NULL to card->event_wq, no error return code of rsxx_pci_probe() is assigned.
To fix this bug, st is assigned with -ENOMEM in this case.
--- drivers/block/rsxx/core.c | 1 + 1 file changed, 1 insertion(+)
drivers/block/rsxx/core.c +1 -0
@@ -871,6 +871,7 @@ static int rsxx_pci_probe(struct pci_dev *dev, card->event_wq =create_singlethread_workqueue (DRIVER_NAME "_event" );if (!card->event_wq) {dev_err (CARD_TO_DEV (card),"Failed card event setup.\n" ); + st = -ENOMEM ; goto failed_event_handler; }
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 250/306 drm/ttm: Fix TTM page pool accounting
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Anthony DeRossi <[email protected]>
[ Upstream commit ca63d76fd2319db984f2875992643f900caf2c72 ]
Freed pages are not subtracted from the allocated_pages counter in ttm_pool_type_fini(), causing a leak in the count on device removal. The next shrinker invocation loops forever trying to free pages that are no longer in the pool:
rcu: INFO: rcu_sched self-detected stall on CPU
rcu: 3-....: (9998 ticks this GP) idle=54e/1/0x4000000000000000 softirq=434857/434857 fqs=2237
(t=10001 jiffies g=2194533 q=49211)
NMI backtrace for cpu 3
CPU: 3 PID: 1034 Comm: kswapd0 Tainted: P O 5.11.0-com #1
Hardware name: System manufacturer System Product Name/PRIME X570-PRO, BIOS 1405 11/19/2019
Call Trace:
<IRQ>
...
</IRQ>
sysvec_apic_timer_interrupt+0x77/0x80
asm_sysvec_apic_timer_interrupt+0x12/0x20
RIP: 0010:mutex_unlock+0x16/0x20
Code: e7 48 8b 70 10 e8 7a 53 77 ff eb aa e8 43 6c ff ff 0f 1f 00 65 48 8b 14 25 00 6d 01 00 31 c9 48 89 d0 f0 48 0f b1 0f 48 39 c2 <74> 05 e9 e3 fe ff ff c3 66 90 48 8b 47 20 48 85 c0 74 0f 8b 50 10
RSP: 0018:ffffbdb840797be8 EFLAGS: 00000246
RAX: ffff9ff445a41c00 RBX: ffffffffc02a9ef8 RCX: 0000000000000000
RDX: ffff9ff445a41c00 RSI: ffffbdb840797c78 RDI: ffffffffc02a9ac0
RBP: 0000000000000080 R08: 0000000000000000 R09: ffffbdb840797c80
R10: 0000000000000000 R11: fffffffffffffff5 R12: 0000000000000000
R13: 0000000000000000 R14: 0000000000000084 R15: ffffffffc02a9a60
ttm_pool_shrink+0x7d/0x90 [ttm]
ttm_pool_shrinker_scan+0x5/0x20 [ttm]
do_shrink_slab+0x13a/0x1a0...
debugfs shows the incorrect total:
$ cat /sys/kernel/debug/dri/0/ttm_page_pool
--- 0--- --- 1--- --- 2--- --- 3--- --- 4--- --- 5--- --- 6--- --- 7--- --- 8--- --- 9--- ---10---
wc : 0 0 0 0 0 0 0 0 0 0 0
uc : 0 0 0 0 0 0 0 0 0 0 0
wc 32 : 0 0 0 0 0 0 0 0 0 0 0
uc 32 : 0 0 0 0 0 0 0 0 0 0 0
DMA uc : 0 0 0 0 0 0 0 0 0 0 0
DMA wc : 0 0 0 0 0 0 0 0 0 0 0
DMA : 0 0 0 0 0 0 0 0 0 0 0total : 3029 of 8244261
Using ttm_pool_type_take() to remove pages from the pool before freeing them correctly accounts for the freed pages.
--- drivers/gpu/drm/ttm/ttm_pool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/ttm/ttm_pool.c +2 -2
@@ -268,13 +268,13 @@ static void ttm_pool_type_init(struct ttm_pool_type *pt, struct ttm_pool *pool,/* Remove a pool_type from the global shrinker list and free all pages */ static void ttm_pool_type_fini (struct ttm_pool_type *pt) { -struct page *p, *tmp; +struct page *p;mutex_lock (&shrinker_lock);list_del (&pt->shrinker_list);mutex_unlock (&shrinker_lock); -list_for_each_entry_safe (p, tmp, &pt->pages, lru) +while ((p =ttm_pool_type_take (pt)))ttm_pool_free_page (pt->pool, pt->caching, pt->order, p); }
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 251/306 nvme-fc: fix racing controller reset and create association
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: James Smart <[email protected]>
[ Upstream commit f20ef34d71abc1fc56b322aaa251f90f94320140 ]
Recent patch to prevent calling __nvme_fc_abort_outstanding_ios in interrupt context results in a possible race condition. A controller reset results in errored io completions, which schedules error work. The change of error work to a work element allows it to fire after the ctrl state transition to NVME_CTRL_CONNECTING, causing any outstanding io (used to initialize the controller) to fail and cause problems for connect_work.
Add a state check to only schedule error work if not in the RESETTING state.
--- drivers/nvme/host/fc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/nvme/host/fc.c +1 -1
@@ -2055,7 +2055,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)nvme_fc_complete_rq (rq); check_error: -if (terminate_assoc) +if (terminate_assoc && ctrl->ctrl.state !=NVME_CTRL_RESETTING )queue_work (nvme_reset_wq, &ctrl->ioerr_work); }
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 252/306 configfs: fix a use-after-free in __configfs_open_file
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Daiyue Zhang <[email protected]>
[ Upstream commit 14fbbc8297728e880070f7b077b3301a8c698ef9 ]
Commit b0841eefd969 ("configfs: provide exclusion between IO and removals") uses ->frag_dead to mark the fragment state, thus no bothering with extra refcount on config_item when opening a file. The configfs_get_config_item was removed in __configfs_open_file, but not with config_item_put. So the refcount on config_item will lost its balance, causing use-after-free issues in some occasions like this:
Test:
1. Mount configfs on /config with read-only items:
drwxrwx--- 289 root root 0 2021-04-01 11:55 /config drwxr-xr-x 2 root root 0 2021-04-01 11:54 /config/a --w--w--w- 1 root root 4096 2021-04-01 11:53 /config/a/1.txt
......
2. Then run:
for file in /config
do
echo $file
grep -R 'key' $file
done
3. __configfs_open_file will be called in parallel, the first one got called will do:
if (file->f_mode & FMODE_READ) {
if (!(inode->i_mode & S_IRUGO))
goto out_put_module;
config_item_put(buffer->item);
kref_put()
package_details_release()
kfree()the other one will run into use-after-free issues like this:
BUG: KASAN: use-after-free in __configfs_open_file+0x1bc/0x3b0 Read of size 8 at addr fffffff155f02480 by task grep/13096 CPU: 0 PID: 13096 Comm: grep VIP: 00 Tainted: G W 4.14.116-kasan #1 TGID: 13096 Comm: grep Call trace: dump_stack+0x118/0x160 kasan_report+0x22c/0x294 __asan_load8+0x80/0x88 __configfs_open_file+0x1bc/0x3b0 configfs_open_file+0x28/0x34 do_dentry_open+0x2cc/0x5c0 vfs_open+0x80/0xe0 path_openat+0xd8c/0x2988 do_filp_open+0x1c4/0x2fc do_sys_open+0x23c/0x404 SyS_openat+0x38/0x48 Allocated by task 2138: kasan_kmalloc+0xe0/0x1ac kmem_cache_alloc_trace+0x334/0x394 packages_make_item+0x4c/0x180 configfs_mkdir+0x358/0x740 vfs_mkdir2+0x1bc/0x2e8 SyS_mkdirat+0x154/0x23c el0_svc_naked+0x34/0x38 Freed by task 13096: kasan_slab_free+0xb8/0x194 kfree+0x13c/0x910 package_details_release+0x524/0x56c kref_put+0xc4/0x104 config_item_put+0x24/0x34 __configfs_open_file+0x35c/0x3b0 configfs_open_file+0x28/0x34 do_dentry_open+0x2cc/0x5c0 vfs_open+0x80/0xe0 path_openat+0xd8c/0x2988 do_filp_open+0x1c4/0x2fc do_sys_open+0x23c/0x404 SyS_openat+0x38/0x48 el0_svc_naked+0x34/0x38
To fix this issue, remove the config_item_put in __configfs_open_file to balance the refcount of config_item.
--- fs/configfs/file.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
fs/configfs/file.c +2 -4
@@ -378,7 +378,7 @@ static int __configfs_open_file(struct inode *inode, struct file *file, int type attr =to_attr (dentry);if (!attr) - goto out_put_item; + goto out_free_buffer;if (type &CONFIGFS_ITEM_BIN_ATTR ) { buffer->bin_attr =to_bin_attr (dentry);
@@ -391,7 +391,7 @@ static int __configfs_open_file(struct inode *inode, struct file *file, int type/* Grab the module reference for this attribute if we have one */ error = -ENODEV ;if (!try_module_get (buffer->owner)) - goto out_put_item; + goto out_free_buffer; error = -EACCES ;if (!buffer->item->ci_type)
@@ -435,8 +435,6 @@ static int __configfs_open_file(struct inode *inode, struct file *file, int type out_put_module:module_put (buffer->owner); -out_put_item: -config_item_put (buffer->item); out_free_buffer:up_read (&frag->frag_sem);kfree (buffer);
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 253/306 arm64: mm: use a 48-bit ID map when possible on 52-bit VA builds
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Ard Biesheuvel <[email protected]>
[ Upstream commit 7ba8f2b2d652cd8d8a2ab61f4be66973e70f9f88 ]
52-bit VA kernels can run on hardware that is only 48-bit capable, but configure the ID map as 52-bit by default. This was not a problem until recently, because the special T0SZ value for a 52-bit VA space was never programmed into the TCR register anwyay, and because a 52-bit ID map happens to use the same number of translation levels as a 48-bit one.
This behavior was changed by commit 1401bef703a4 ("arm64: mm: Always update TCR_EL1 from __cpu_set_tcr_t0sz()"), which causes the unsupported T0SZ value for a 52-bit VA to be programmed into TCR_EL1. While some hardware simply ignores this, Mark reports that Amberwing systems choke on this, resulting in a broken boot. But even before that commit, the unsupported idmap_t0sz value was exposed to KVM and used to program TCR_EL2 incorrectly as well.
Given that we already have to deal with address spaces being either 48-bit or 52-bit in size, the cleanest approach seems to be to simply default to a 48-bit VA ID map, and only switch to a 52-bit one if the placement of the kernel in DRAM requires it. This is guaranteed not to happen unless the system is actually 52-bit VA capable.
--- arch/arm64/include/asm/mmu_context.h | 5 +---- arch/arm64/kernel/head.S | 2 +- arch/arm64/mm/mmu.c | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-)
arch/arm64/include/asm/mmu_context.h +1 -4
@@ -65,10 +65,7 @@ extern u64 idmap_ptrs_per_pgd;static inline bool __cpu_uses_extended_idmap (void ) { -if (IS_ENABLED (CONFIG_ARM64_VA_BITS_52 )) -return false; - -return unlikely (idmap_t0sz !=TCR_T0SZ (VA_BITS )); +return unlikely (idmap_t0sz !=TCR_T0SZ (vabits_actual)); }/*
arch/arm64/kernel/head.S +1 -1
@@ -319,7 +319,7 @@ SYM_FUNC_START_LOCAL(__create_page_tables) */ adrp x5, __idmap_text_end clz x5, x5 - cmp x5, TCR_T0SZ(VA_BITS) // default T0SZ small enough? + cmp x5, TCR_T0SZ(VA_BITS_MIN) // default T0SZ small enough? b.ge 1f // .. then skip VA range extension adr_l x6, idmap_t0sz
arch/arm64/mm/mmu.c +1 -1
@@ -40,7 +40,7 @@#define NO_BLOCK_MAPPINGS BIT(0)#define NO_CONT_MAPPINGS BIT(1) -u64 idmap_t0sz =TCR_T0SZ (VA_BITS ); +u64 idmap_t0sz =TCR_T0SZ (VA_BITS_MIN );u64 idmap_ptrs_per_pgd =PTRS_PER_PGD ; u64 __section(".mmuoff.data.write") vabits_actual;
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 254/306 io_uring: perform IOPOLL reaping if canceler is thread itself
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Jens Axboe <[email protected]>
[ Upstream commit d052d1d685f5125249ab4ff887562c88ba959638 ]
We bypass IOPOLL completion polling (and reaping) for the SQPOLL thread, but if it's the thread itself invoking cancelations, then we still need to perform it or no one will.
--- fs/io_uring.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/io_uring.c +2 -1
@@ -8891,7 +8891,8 @@ static void io_uring_try_cancel_requests(struct io_ring_ctx *ctx, }/* SQPOLL thread does its own polling */ -if (!(ctx->flags &IORING_SETUP_SQPOLL ) && !files) { +if ((!(ctx->flags &IORING_SETUP_SQPOLL ) && !files) || + (ctx->sq_data && ctx->sq_data->thread == current)) {while (!list_empty_careful (&ctx->iopoll_list)) {io_iopoll_try_reap_events (ctx); ret = true;
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 255/306 drm/nouveau: fix dma syncing for loops (v2)
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Dave Airlie <[email protected]>
[ Upstream commit 4042160c2e5433e0759782c402292a90b5bf458d ]
The index variable should only be increased in one place.
Noticed this while trying to track down another oops.
v2: use while loop.
--- drivers/gpu/drm/nouveau/nouveau_bo.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/gpu/drm/nouveau/nouveau_bo.c +4 -2
@@ -556,7 +556,8 @@ nouveau_bo_sync_for_device(struct nouveau_bo *nvbo)if (nvbo->force_coherent)return ; -for (i =0 ; i < ttm_dma->num_pages; ++i) { + i =0 ; +while (i < ttm_dma->num_pages) {struct page *p = ttm_dma->pages[i];size_t num_pages =1 ;
@@ -587,7 +588,8 @@ nouveau_bo_sync_for_cpu(struct nouveau_bo *nvbo)if (nvbo->force_coherent)return ; -for (i =0 ; i < ttm_dma->num_pages; ++i) { + i =0 ; +while (i < ttm_dma->num_pages) {struct page *p = ttm_dma->pages[i];size_t num_pages =1 ;
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 256/306 perf/arm_dmc620_pmu: Fix error return code in dmc620_pmu_device_probe()
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Wei Yongjun <[email protected]>
[ Upstream commit c8e3866836528a4ba3b0535834f03768d74f7d8e ]
Fix to return negative error code -ENOMEM from the error handling case instead of 0, as done elsewhere in this function.
--- drivers/perf/arm_dmc620_pmu.c | 1 + 1 file changed, 1 insertion(+)
drivers/perf/arm_dmc620_pmu.c +1 -0
@@ -681,6 +681,7 @@ static int dmc620_pmu_device_probe(struct platform_device *pdev)if (!name) {dev_err (&pdev->dev,"Create name failed, PMU @%pa\n" , &res->start); + ret = -ENOMEM ; goto out_teardown_dev; }
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 257/306 net: expand textsearch ts_state to fit skb_seq_state
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Willem de Bruijn <[email protected]>
[ Upstream commit b228c9b058760500fda5edb3134527f629fc2dc3 ]
The referenced commit expands the skb_seq_state used by skb_find_text with a 4B frag_off field, growing it to 48B.
This exceeds container ts_state->cb, causing a stack corruption:
[ 73.238353] Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: skb_find_text+0xc5/0xd0 [ 73.247384] CPU: 1 PID: 376 Comm: nping Not tainted 5.11.0+ #4 [ 73.252613] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-2 04/01/2014 [ 73.260078] Call Trace: [ 73.264677] dump_stack+0x57/0x6a [ 73.267866] panic+0xf6/0x2b7 [ 73.270578] ? skb_find_text+0xc5/0xd0 [ 73.273964] __stack_chk_fail+0x10/0x10 [ 73.277491] skb_find_text+0xc5/0xd0 [ 73.280727] string_mt+0x1f/0x30 [ 73.283639] ipt_do_table+0x214/0x410
The struct is passed between skb_find_text and its callbacks skb_prepare_seq_read, skb_seq_read and skb_abort_seq read through the textsearch interface using TS_SKB_CB.
I assumed that this mapped to skb->cb like other .._SKB_CB wrappers. skb->cb is 48B. But it maps to ts_state->cb, which is only 40B.
skb->cb was increased from 40B to 48B after ts_state was introduced, in commit 3e3850e989c5 ("[NETFILTER]: Fix xfrm lookup in ip_route_me_harder/ip6_route_me_harder").
Increase ts_state.cb[] to 48 to fit the struct.
Also add a BUILD_BUG_ON to avoid a repeat.
The alternative is to directly add a dependency from textsearch onto linux/skbuff.h, but I think the intent is textsearch to have no such dependencies on its callers.
--- include/linux/textsearch.h | 2 +- net/core/skbuff.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-)
include/linux/textsearch.h +1 -1
@@ -23,7 +23,7 @@ struct ts_config;struct ts_state {unsigned int offset; -char cb[40 ]; +char cb[48 ]; };/**
net/core/skbuff.c +2 -0
@@ -3622,6 +3622,8 @@ unsigned int skb_find_text(struct sk_buff *skb, unsigned int from,struct ts_state state;unsigned int ret; +BUILD_BUG_ON (sizeof (struct skb_seq_state ) >sizeof (state.cb)); + config->get_next_block = skb_ts_get_next_block; config->finish = skb_ts_finish;
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 258/306 mptcp: put subflow sock on connect error
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Florian Westphal <[email protected]>
[ Upstream commit f07157792c633b528de5fc1dbe2e4ea54f8e09d4 ]
mptcp_add_pending_subflow() performs a sock_hold() on the subflow, then adds the subflow to the join list.
Without a sock_put the subflow sk won't be freed in case connect() fails.
unreferenced object 0xffff88810c03b100 (size 3000):
[..]
sk_prot_alloc.isra.0+0x2f/0x110
sk_alloc+0x5d/0xc20
inet6_create+0x2b7/0xd30
__sock_create+0x17f/0x410
mptcp_subflow_create_socket+0xff/0x9c0
__mptcp_subflow_connect+0x1da/0xaf0
mptcp_pm_nl_work+0x6e0/0x1120
mptcp_worker+0x508/0x9a0--- net/mptcp/subflow.c | 1 + 1 file changed, 1 insertion(+)
net/mptcp/subflow.c +1 -0
@@ -1174,6 +1174,7 @@ int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,spin_lock_bh (&msk->join_list_lock);list_del (&subflow->node);spin_unlock_bh (&msk->join_list_lock); +sock_put (mptcp_subflow_tcp_sock (subflow)); failed: subflow->disposable =1 ;
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 259/306 mptcp: fix memory accounting on allocation error
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Paolo Abeni <[email protected]>
[ Upstream commit eaeef1ce55ec9161e0c44ff27017777b1644b421 ]
In case of memory pressure the MPTCP xmit path keeps at most a single skb in the tx cache, eventually freeing additional ones.
The associated counter for forward memory is not update accordingly, and that causes the following splat:
WARNING: CPU: 0 PID: 12 at net/core/stream.c:208 sk_stream_kill_queues+0x3ca/0x530 net/core/stream.c:208 Modules linked in: CPU: 0 PID: 12 Comm: kworker/0:1 Not tainted 5.11.0-rc2 #59 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 Workqueue: events mptcp_worker RIP: 0010:sk_stream_kill_queues+0x3ca/0x530 net/core/stream.c:208 Code: 03 0f b6 04 02 84 c0 74 08 3c 03 0f 8e 63 01 00 00 8b ab 00 01 00 00 e9 60 ff ff ff e8 2f 24 d3 fe 0f 0b eb 97 e8 26 24 d3 fe <0f> 0b eb a0 e8 1d 24 d3 fe 0f 0b e9 a5 fe ff ff 4c 89 e7 e8 0e d0 RSP: 0018:ffffc900000c7bc8 EFLAGS: 00010293 RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000 RDX: ffff88810030ac40 RSI: ffffffff8262ca4a RDI: 0000000000000003 RBP: 0000000000000d00 R08: 0000000000000000 R09: ffffffff85095aa7 R10: ffffffff8262c9ea R11: 0000000000000001 R12: ffff888108908100 R13: ffffffff85095aa0 R14: ffffc900000c7c48 R15: 1ffff92000018f85 FS: 0000000000000000(0000) GS:ffff88811b200000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fa7444baef8 CR3: 0000000035ee9005 CR4: 0000000000170ef0 Call Trace: __mptcp_destroy_sock+0x4a7/0x6c0 net/mptcp/protocol.c:2547 mptcp_worker+0x7dd/0x1610 net/mptcp/protocol.c:2272 process_one_work+0x896/0x1170 kernel/workqueue.c:2275 worker_thread+0x605/0x1350 kernel/workqueue.c:2421 kthread+0x344/0x410 kernel/kthread.c:292 ret_from_fork+0x22/0x30 arch/x86/entry/entry_64.S:296
At close time, as reported by syzkaller/Christoph.
This change address the issue properly updating the fwd allocated memory counter in the error path.
--- net/mptcp/protocol.c | 1 + 1 file changed, 1 insertion(+)
net/mptcp/protocol.c +1 -0
@@ -1176,6 +1176,7 @@ static bool mptcp_tx_cache_refill(struct sock *sk, int size,*/ while (skbs->qlen >1 ) { skb =__skb_dequeue_tail (skbs); + *total_ts -= skb->truesize;__kfree_skb (skb); }return skbs->qlen >0 ;
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 260/306 perf/core: Flush PMU internal buffers for per-CPU events
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Kan Liang <[email protected]>
[ Upstream commit a5398bffc01fe044848c5024e5e867e407f239b8 ]
Sometimes the PMU internal buffers have to be flushed for per-CPU events during a context switch, e.g., large PEBS. Otherwise, the perf tool may report samples in locations that do not belong to the process where the samples are processed in, because PEBS does not tag samples with PID/TID.
The current code only flush the buffers for a per-task event. It doesn't check a per-CPU event.
Add a new event state flag, PERF_ATTACH_SCHED_CB, to indicate that the PMU internal buffers have to be flushed for this event during a context switch.
Add sched_cb_entry and perf_sched_cb_usages back to track the PMU/cpuctx which is required to be flushed.
Only need to invoke the sched_task() for per-CPU events in this patch. The per-task events have been handled in perf_event_context_sched_in/out already.
--- include/linux/perf_event.h | 2 ++ kernel/events/core.c | 42 ++++++++++++++++++++++++++++++++++---- 2 files changed, 40 insertions(+), 4 deletions(-)
include/linux/perf_event.h +2 -0
@@ -606,6 +606,7 @@ struct swevent_hlist {#define PERF_ATTACH_TASK 0x04#define PERF_ATTACH_TASK_DATA 0x08#define PERF_ATTACH_ITRACE 0x10 +#define PERF_ATTACH_SCHED_CB 0x20struct perf_cgroup ;struct perf_buffer ;
@@ -872,6 +873,7 @@ struct perf_cpu_context {struct list_head cgrp_cpuctx_entry;#endif +struct list_head sched_cb_entry;int sched_cb_usage;int online;
kernel/events/core.c +38 -4
100 lines not on this page · raw message
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 261/306 perf/x86/intel: Set PERF_ATTACH_SCHED_CB for large PEBS and LBR
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Kan Liang <[email protected]>
[ Upstream commit afbef30149587ad46f4780b1e0cc5e219745ce90 ]
To supply a PID/TID for large PEBS, it requires flushing the PEBS buffer in a context switch.
For normal LBRs, a context switch can flip the address space and LBR entries are not tagged with an identifier, we need to wipe the LBR, even for per-cpu events.
For LBR callstack, save/restore the stack is required during a context switch.
Set PERF_ATTACH_SCHED_CB for the event with large PEBS & LBR.
--- arch/x86/events/intel/core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
arch/x86/events/intel/core.c +4 -1
@@ -3578,8 +3578,10 @@ static int intel_pmu_hw_config(struct perf_event *event)if (!(event->attr.freq || (event->attr.wakeup_events && !event->attr.watermark))) { event->hw.flags |=PERF_X86_EVENT_AUTO_RELOAD ;if (!(event->attr.sample_type & - ~intel_pmu_large_pebs_flags (event))) + ~intel_pmu_large_pebs_flags (event))) { event->hw.flags |=PERF_X86_EVENT_LARGE_PEBS ; + event->attach_state |=PERF_ATTACH_SCHED_CB ; + } }if (x86_pmu.pebs_aliases) x86_pmu.pebs_aliases (event);
@@ -3592,6 +3594,7 @@ static int intel_pmu_hw_config(struct perf_event *event) ret =intel_pmu_setup_lbr_filter (event);if (ret)return ret; + event->attach_state |=PERF_ATTACH_SCHED_CB ;/* * BTS is set up earlier in this path, so don't account twice
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 262/306 hrtimer: Update softirq_expires_next correctly after __hrtimer_get_next_event()
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Anna-Maria Behnsen <[email protected]>
[ Upstream commit 46eb1701c046cc18c032fa68f3c8ccbf24483ee4 ]
hrtimer_force_reprogram() and hrtimer_interrupt() invokes __hrtimer_get_next_event() to find the earliest expiry time of hrtimer bases. __hrtimer_get_next_event() does not update cpu_base::[softirq_]_expires_next to preserve reprogramming logic. That needs to be done at the callsites.
hrtimer_force_reprogram() updates cpu_base::softirq_expires_next only when the first expiring timer is a softirq timer and the soft interrupt is not activated. That's wrong because cpu_base::softirq_expires_next is left stale when the first expiring timer of all bases is a timer which expires in hard interrupt context. hrtimer_interrupt() does never update cpu_base::softirq_expires_next which is wrong too.
That becomes a problem when clock_settime() sets CLOCK_REALTIME forward and the first soft expiring timer is in the CLOCK_REALTIME_SOFT base. Setting CLOCK_REALTIME forward moves the clock MONOTONIC based expiry time of that timer before the stale cpu_base::softirq_expires_next.
cpu_base::softirq_expires_next is cached to make the check for raising the soft interrupt fast. In the above case the soft interrupt won't be raised until clock monotonic reaches the stale cpu_base::softirq_expires_next value. That's incorrect, but what's worse it that if the softirq timer becomes the first expiring timer of all clock bases after the hard expiry timer has been handled the reprogramming of the clockevent from hrtimer_interrupt() will result in an interrupt storm. That happens because the reprogramming does not use cpu_base::softirq_expires_next, it uses __hrtimer_get_next_event() which returns the actual expiry time. Once clock MONOTONIC reaches cpu_base::softirq_expires_next the soft interrupt is raised and the storm subsides.
Change the logic in hrtimer_force_reprogram() to evaluate the soft and hard bases seperately, update softirq_expires_next and handle the case when a soft expiring timer is the first of all bases by comparing the expiry times and updating the required cpu base fields. Split this functionality into a separate function to be able to use it in hrtimer_interrupt() as well without copy paste.
--- kernel/time/hrtimer.c | 60 ++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 21 deletions(-)
kernel/time/hrtimer.c +39 -21
@@ -546,8 +546,11 @@ static ktime_t __hrtimer_next_event_base(struct hrtimer_cpu_base *cpu_base, }/* -* Recomputes cpu_base::*next_timer and returns the earliest expires_next but -* does not set cpu_base::*expires_next, that is done by hrtimer_reprogram. +* Recomputes cpu_base::*next_timer and returns the earliest expires_next +* but does not set cpu_base::*expires_next, that is done by +* hrtimer[_force]_reprogram and hrtimer_interrupt only. When updating +* cpu_base::*expires_next right away, reprogramming logic would no longer +* work. * * When a softirq is pending, we can ignore the HRTIMER_ACTIVE_SOFT bases, * those timers will get run whenever the softirq gets handled, at the end of
@@ -588,6 +591,37 @@ __hrtimer_get_next_event(struct hrtimer_cpu_base *cpu_base, unsigned int active_return expires_next; } +static ktime_t hrtimer_update_next_event (struct hrtimer_cpu_base *cpu_base) +{ +ktime_t expires_next, soft =KTIME_MAX ; + +/* +* If the soft interrupt has already been activated, ignore the +* soft bases. They will be handled in the already raised soft +* interrupt. +*/ +if (!cpu_base->softirq_activated) { + soft =__hrtimer_get_next_event (cpu_base,HRTIMER_ACTIVE_SOFT ); +/* +* Update the soft expiry time. clock_settime() might have +* affected it. +*/ + cpu_base->softirq_expires_next = soft; + } + + expires_next =__hrtimer_get_next_event (cpu_base,HRTIMER_ACTIVE_HARD ); +/* +* If a softirq timer is expiring first, update cpu_base->next_timer +* and program the hardware with the soft expiry time. +*/ +if (expires_next > soft) { + cpu_base->next_timer = cpu_base->softirq_next_timer; + expires_next = soft; + } + +return expires_next; +} +static inline ktime_t hrtimer_update_base (struct hrtimer_cpu_base *base) {ktime_t *offs_real = &base->clock_base[HRTIMER_BASE_REALTIME ].offset;
@@ -628,23 +662,7 @@ hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base, int skip_equal) {ktime_t expires_next; -/* -* Find the current next expiration time. -*/ - expires_next =__hrtimer_get_next_event (cpu_base,HRTIMER_ACTIVE_ALL ); - -if (cpu_base->next_timer && cpu_base->next_timer->is_soft) { -/* -* When the softirq is activated, hrtimer has to be -* programmed with the first hard hrtimer because soft -* timer interrupt could occur too late. -*/ -if (cpu_base->softirq_activated) - expires_next =__hrtimer_get_next_event (cpu_base, -HRTIMER_ACTIVE_HARD ); -else - cpu_base->softirq_expires_next = expires_next; - } + expires_next =hrtimer_update_next_event (cpu_base);if (skip_equal && expires_next == cpu_base->expires_next)return ;
@@ -1644,8 +1662,8 @@ void hrtimer_interrupt(struct clock_event_device *dev)__hrtimer_run_queues (cpu_base, now, flags,HRTIMER_ACTIVE_HARD ); -/* Reevaluate the clock bases for the next expiry */ - expires_next =__hrtimer_get_next_event (cpu_base,HRTIMER_ACTIVE_ALL ); +/* Reevaluate the clock bases for the [soft] next expiry */ + expires_next =hrtimer_update_next_event (cpu_base);/* * Store the new expiry value so the migration code can verify * against it.
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 263/306 powerpc/64s/exception: Clean up a missed SRR specifier
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Daniel Axtens <[email protected]>
[ Upstream commit c080a173301ffc62cb6c76308c803c7fee05517a ]
Nick's patch cleaning up the SRR specifiers in exception-64s.S missed a single instance of EXC_HV_OR_STD. Clean that up.
Caught by clang's integrated assembler.
--- arch/powerpc/kernel/exceptions-64s.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/kernel/exceptions-64s.S +1 -1
@@ -470,7 +470,7 @@ DEFINE_FIXED_SYMBOL(\name\()_common_real) ld r10,PACAKMSR(r13) /* get MSR value for kernel */ /* MSR[RI] is clear iff using SRR regs */ - .if IHSRR == EXC_HV_OR_STD + .if IHSRR_IF_HVMODE BEGIN_FTR_SECTION xori r10,r10,MSR_RI END_FTR_SECTION_IFCLR(CPU_FTR_HVMODE)
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 264/306 seqlock,lockdep: Fix seqcount_latch_init()
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Peter Zijlstra <[email protected]>
[ Upstream commit 4817a52b306136c8b2b2271d8770401441e4cf79 ]
seqcount_init() must be a macro in order to preserve the static variable that is used for the lockdep key. Don't then wrap it in an inline function, which destroys that.
Luckily there aren't many users of this function, but fix it before it becomes a problem.
--- include/linux/seqlock.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
include/linux/seqlock.h +1 -4
@@ -664,10 +664,7 @@ typedef struct {* seqcount_latch_init() - runtime initializer for seqcount_latch_t * @s: Pointer to the seqcount_latch_t instance */ -static inline void seqcount_latch_init (seqcount_latch_t *s) -{ -seqcount_init (&s->seqcount); -} +#define seqcount_latch_init (s) seqcount_init(&(s)->seqcount)/** * raw_read_seqcount_latch() - pick even/odd latch data copy
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 265/306 memblock: fix section mismatch warning
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Arnd Bergmann <[email protected]>
[ Upstream commit 34dc2efb39a231280fd6696a59bbe712bf3c5c4a ]
The inlining logic in clang-13 is rewritten to often not inline some functions that were inlined by all earlier compilers.
In case of the memblock interfaces, this exposed a harmless bug of a missing __init annotation:
WARNING: modpost: vmlinux.o(.text+0x507c0a): Section mismatch in reference from the function memblock_bottom_up() to the variable .meminit.data:memblock The function memblock_bottom_up() references
the variable __meminitdata memblock.
This is often because memblock_bottom_up lacks a __meminitdata
annotation or the annotation of memblock is wrong.
Interestingly, these annotations were present originally, but got removed with the explanation that the __init annotation prevents the function from getting inlined. I checked this again and found that while this is the case with clang, gcc (version 7 through 10, did not test others) does inline the functions regardless.
As the previous change was apparently intended to help the clang builds, reverting it to help the newer clang versions seems appropriate as well. gcc builds don't seem to care either way.
Reference: 2cfb3665e864 ("include/linux/memblock.h: add __init to memblock_set_bottom_up()")
--- include/linux/memblock.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
include/linux/memblock.h +2 -2
@@ -460,7 +460,7 @@ static inline void memblock_free_late(phys_addr_t base, phys_addr_t size)/* * Set the allocation direction to bottom-up or top-down. */ -static inline void memblock_set_bottom_up (bool enable) +static inline __init void memblock_set_bottom_up (bool enable) { memblock.bottom_up = enable; }
@@ -470,7 +470,7 @@ static inline void memblock_set_bottom_up(bool enable)* if this is true, that said, memblock will allocate memory * in bottom-up direction. */ -static inline bool memblock_bottom_up (void ) +static inline __init bool memblock_bottom_up (void ) {return memblock.bottom_up; }
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 266/306 stop_machine: mark helpers __always_inline
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Arnd Bergmann <[email protected]>
[ Upstream commit cbf78d85079cee662c45749ef4f744d41be85d48 ]
With clang-13, some functions only get partially inlined, with a specialized version referring to a global variable. This triggers a harmless build-time check for the intel-rng driver:
WARNING: modpost: drivers/char/hw_random/intel-rng.o(.text+0xe): Section mismatch in reference from the function stop_machine() to the function .init.text:intel_rng_hw_init() The function stop_machine() references
the function __init intel_rng_hw_init().
This is often because stop_machine lacks a __init
annotation or the annotation of intel_rng_hw_init is wrong.
In this instance, an easy workaround is to force the stop_machine() function to be inline, along with related interfaces that did not show the same behavior at the moment, but theoretically could.
The combination of the two patches listed below triggers the behavior in clang-13, but individually these commits are correct.
--- include/linux/stop_machine.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
include/linux/stop_machine.h +6 -5
@@ -128,7 +128,7 @@ int stop_machine_from_inactive_cpu(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus);#else /* CONFIG_SMP || CONFIG_HOTPLUG_CPU */ -static inline int stop_machine_cpuslocked (cpu_stop_fn_t fn,void *data, +static __always_inline int stop_machine_cpuslocked(cpu_stop_fn_t fn, void *data,const struct cpumask *cpus) {unsigned long flags;
@@ -139,14 +139,15 @@ static inline int stop_machine_cpuslocked(cpu_stop_fn_t fn, void *data,return ret; } -static inline int stop_machine (cpu_stop_fn_t fn,void *data, -const struct cpumask *cpus) +static __always_inline int +stop_machine (cpu_stop_fn_t fn,void *data,const struct cpumask *cpus) {return stop_machine_cpuslocked (fn, data, cpus); } -static inline int stop_machine_from_inactive_cpu (cpu_stop_fn_t fn,void *data, -const struct cpumask *cpus) +static __always_inline int +stop_machine_from_inactive_cpu (cpu_stop_fn_t fn,void *data, +const struct cpumask *cpus) {return stop_machine (fn, data, cpus); }
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 267/306 include/linux/sched/mm.h: use rcu_dereference in in_vfork()
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Matthew Wilcox (Oracle) <[email protected]>
[ Upstream commit 149fc787353f65b7e72e05e7b75d34863266c3e2 ]
Fix a sparse warning by using rcu_dereference(). Technically this is a bug and a sufficiently aggressive compiler could reload the `real_parent' pointer outside the protection of the rcu lock (and access freed memory), but I think it's pretty unlikely to happen.
--- include/linux/sched/mm.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
include/linux/sched/mm.h +2 -1
@@ -140,7 +140,8 @@ static inline bool in_vfork(struct task_struct *tsk)* another oom-unkillable task does this it should blame itself. */ rcu_read_lock (); - ret = tsk->vfork_done && tsk->real_parent->mm == tsk->mm; + ret = tsk->vfork_done && +rcu_dereference (tsk->real_parent)->mm == tsk->mm;rcu_read_unlock ();return ret;
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 268/306 prctl: fix PR_SET_MM_AUXV kernel stack leak
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Alexey Dobriyan <[email protected]>
[ Upstream commit c995f12ad8842dbf5cfed113fb52cdd083f5afd1 ]
Doing a
prctl(PR_SET_MM, PR_SET_MM_AUXV, addr, 1);
will copy 1 byte from userspace to (quite big) on-stack array and then stash everything to mm->saved_auxv. AT_NULL terminator will be inserted at the very end.
/proc/*/auxv handler will find that AT_NULL terminator and copy original stack contents to userspace.
This devious scheme requires CAP_SYS_RESOURCE.
--- kernel/sys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/sys.c +1 -1
@@ -2080,7 +2080,7 @@ static int prctl_set_auxv(struct mm_struct *mm, unsigned long addr,* up to the caller to provide sane values here, otherwise userspace * tools which use this vector might be unhappy. */ -unsigned long user_auxv[AT_VECTOR_SIZE ]; +unsigned long user_auxv[AT_VECTOR_SIZE ] = {};if (len >sizeof (user_auxv))return -EINVAL ;
Signature · 1 line
2.30.1
[email protected]
maintainerPATCH 269/306 zram: fix return value on writeback_store
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Minchan Kim <[email protected]>
commit 57e0076e6575a7b7cef620a0bd2ee2549ef77818 upstream.
writeback_store's return value is overwritten by submit_bio_wait's return value. Thus, writeback_store will return zero since there was no IO error. In the end, write syscall from userspace will see the zero as return value, which could make the process stall to keep trying the write until it will succeed.
--- drivers/block/zram/zram_drv.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
drivers/block/zram/zram_drv.c +8 -3
@@ -628,7 +628,7 @@ static ssize_t writeback_store(struct destruct bio_vec bio_vec;struct page *page;ssize_t ret = len; -int mode; +int mode, err;unsigned long blk_idx =0 ;if (sysfs_streq (buf,"idle" ))
@@ -729,12 +729,17 @@ static ssize_t writeback_store(struct de* XXX: A single page IO would be inefficient for write * but it would be not bad as starter. */ - ret =submit_bio_wait (&bio); -if (ret) { + err =submit_bio_wait (&bio); +if (err) {zram_slot_lock (zram, index);zram_clear_flag (zram, index,ZRAM_UNDER_WB );zram_clear_flag (zram, index,ZRAM_IDLE );zram_slot_unlock (zram, index); +/* +* Return last IO error unless every IO were +* not suceeded. +*/ + ret = err;continue ; }
[email protected]
maintainerPATCH 270/306 zram: fix broken page writeback
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Minchan Kim <[email protected]>
commit 2766f1821600cc7562bae2128ad0b163f744c5d9 upstream.
commit 0d8359620d9b ("zram: support page writeback") introduced two problems. It overwrites writeback_store's return value as kstrtol's return value, which makes return value zero so user could see zero as return value of write syscall even though it wrote data successfully.
It also breaks index value in the loop in that it doesn't increase the index any longer. It means it can write only first starting block index so user couldn't write all idle pages in the zram so lose memory saving chance.
This patch fixes those issues.
--- drivers/block/zram/zram_drv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/block/zram/zram_drv.c +3 -3
@@ -639,8 +639,8 @@ static ssize_t writeback_store(struct deif (strncmp (buf,PAGE_WB_SIG ,sizeof (PAGE_WB_SIG ) -1 ))return -EINVAL ; - ret =kstrtol (buf +sizeof (PAGE_WB_SIG ) -1 ,10 , &index); -if (ret || index >= nr_pages) +if (kstrtol (buf +sizeof (PAGE_WB_SIG ) -1 ,10 , &index) || + index >= nr_pages)return -EINVAL ; nr_pages =1 ;
@@ -664,7 +664,7 @@ static ssize_t writeback_store(struct de goto release_init_lock; } -while (nr_pages--) { +for (; nr_pages !=0 ; index++, nr_pages--) {struct bio_vec bvec; bvec.bv_page = page;
[email protected]
maintainerPATCH 271/306 linux/compiler-clang.h: define HAVE_BUILTIN_BSWAP*
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Arnd Bergmann <[email protected]>
commit 97e4910232fa1f81e806aa60c25a0450276d99a2 upstream.
Separating compiler-clang.h from compiler-gcc.h inadventently dropped the definitions of the three HAVE_BUILTIN_BSWAP macros, which requires falling back to the open-coded version and hoping that the compiler detects it.
Since all versions of clang support the __builtin_bswap interfaces, add back the flags and have the headers pick these up automatically.
This results in a 4% improvement of compilation speed for arm defconfig.
Note: it might also be worth revisiting which architectures set CONFIG_ARCH_USE_BUILTIN_BSWAP for one compiler or the other, today this is set on six architectures (arm32, csky, mips, powerpc, s390, x86), while another ten architectures define custom helpers (alpha, arc, ia64, m68k, mips, nios2, parisc, sh, sparc, xtensa), and the rest (arm64, h8300, hexagon, microblaze, nds32, openrisc, riscv) just get the unoptimized version and rely on the compiler to detect it.
A long time ago, the compiler builtins were architecture specific, but nowadays, all compilers that are able to build the kernel have correct implementations of them, though some may not be as optimized as the inline asm versions.
The patch that dropped the optimization landed in v4.19, so as discussed it would be fairly safe to backport this revert to stable kernels to the 4.19/5.4/5.10 stable kernels, but there is a remaining risk for regressions, and it has no known side-effects besides compile speed.
--- include/linux/compiler-clang.h | 6 ++++++ 1 file changed, 6 insertions(+)
include/linux/compiler-clang.h +6 -0
@@ -41,6 +41,12 @@#define __no_sanitize_thread#endif +#if defined(CONFIG_ARCH_USE_BUILTIN_BSWAP ) +#define __HAVE_BUILTIN_BSWAP32__ +#define __HAVE_BUILTIN_BSWAP64__ +#define __HAVE_BUILTIN_BSWAP16__ +#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */ +#if __has_feature (undefined_behavior_sanitizer)/* GCC does not have __SANITIZE_UNDEFINED__ */ #define __no_sanitize_undefined \
[email protected]
maintainerPATCH 272/306 sched: Fix migration_cpu_stop() requeueing
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Peter Zijlstra <[email protected]>
commit 8a6edb5257e2a84720fe78cb179eca58ba76126f upstream.
When affine_move_task(p) is called on a running task @p, which is not otherwise already changing affinity, we'll first set p->migration_pending and then do:
stop_one_cpu(cpu_of_rq(rq), migration_cpu_stop, &arg);
This then gets us to migration_cpu_stop() running on the CPU that was previously running our victim task @p.
If we find that our task is no longer on that runqueue (this can happen because of a concurrent migration due to load-balance etc.), then we'll end up at the:
} else if (dest_cpu < 1 || pending) {branch. Which we'll take because we set pending earlier. Here we first check if the task @p has already satisfied the affinity constraints, if so we bail early [A]. Otherwise we'll reissue migration_cpu_stop() onto the CPU that is now hosting our task @p:
stop_one_cpu_nowait(cpu_of(rq), migration_cpu_stop, &pending->arg, &pending->stop_work);
Except, we've never initialized pending->arg, which will be all 0s.
This then results in running migration_cpu_stop() on the next CPU with arg->p == NULL, which gives the by now obvious result of fireworks.
The cure is to change affine_move_task() to always use pending->arg, furthermore we can use the exact same pattern as the SCA_MIGRATE_ENABLE case, since we'll block on the pending->done completion anyway, no point in adding yet another completion in stop_one_cpu().
This then gives a clear distinction between the two migration_cpu_stop() use cases:
- sched_exec() / migrate_task_to() : arg->pending == NULL
- affine_move_task() : arg->pending != NULL;
And we can have it ignore p->migration_pending when !arg->pending. Any stop work from sched_exec() / migrate_task_to() is in addition to stop works from affine_move_task(), which will be sufficient to issue the completion.
--- kernel/sched/core.c | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-)
kernel/sched/core.c +28 -11
@@ -1922,6 +1922,24 @@ static int migration_cpu_stop(void *datarq_lock (rq, &rf); pending = p->migration_pending; +if (pending && !arg->pending) { +/* +* This happens from sched_exec() and migrate_task_to(), +* neither of them care about pending and just want a task to +* maybe move about. +* +* Even if there is a pending, we can ignore it, since +* affine_move_task() will have it's own stop_work's in flight +* which will manage the completion. +* +* Notably, pending doesn't need to match arg->pending. This can +* happen when tripple concurrent affine_move_task() first sets +* pending, then clears pending and eventually sets another +* pending. +*/ + pending =NULL ; + } +/* * If task_rq(p) != rq, it cannot be migrated here, because we're * holding rq->lock, if p->on_rq == 0 it cannot get enqueued because
@@ -2194,10 +2212,6 @@ static int affine_move_task(struct rq *r int dest_cpu, unsigned int flags) {struct set_affinity_pending my_pending = { }, *pending =NULL ; -struct migration_arg arg = { - .task = p, - .dest_cpu = dest_cpu, - };bool complete = false;/* Can the task run on the task's current CPU? If so, we're done */
@@ -2235,6 +2249,12 @@ static int affine_move_task(struct rq *r/* Install the request */ refcount_set (&my_pending.refs,1 );init_completion (&my_pending.done); + my_pending.arg = (struct migration_arg ) { + .task = p, + .dest_cpu =-1 ,/* any */ + .pending = &my_pending, + }; + p->migration_pending = &my_pending; }else { pending = p->migration_pending;
@@ -2265,12 +2285,6 @@ static int affine_move_task(struct rq *r p->migration_flags &= ~MDF_PUSH ;task_rq_unlock (rq, p, rf); - pending->arg = (struct migration_arg ) { - .task = p, - .dest_cpu =-1 , - .pending = pending, - }; -stop_one_cpu_nowait (cpu_of (rq), migration_cpu_stop, &pending->arg, &pending->stop_work);
@@ -2283,8 +2297,11 @@ static int affine_move_task(struct rq *r* is_migration_disabled(p) checks to the stopper, which will * run on the same CPU as said p. */ +refcount_inc (&pending->refs);/* pending->{arg,stop_work} */ task_rq_unlock (rq, p, rf); -stop_one_cpu (cpu_of (rq), migration_cpu_stop, &arg); + +stop_one_cpu_nowait (cpu_of (rq), migration_cpu_stop, + &pending->arg, &pending->stop_work); }else {
[email protected]
maintainerPATCH 273/306 sched/membarrier: fix missing local execution of ipi_sync_rq_state()
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Mathieu Desnoyers <[email protected]>
commit ce29ddc47b91f97e7f69a0fb7cbb5845f52a9825 upstream.
The function sync_runqueues_membarrier_state() should copy the membarrier state from the @mm received as parameter to each runqueue currently running tasks using that mm.
However, the use of smp_call_function_many() skips the current runqueue, which is unintended. Replace by a call to on_each_cpu_mask().
--- kernel/sched/membarrier.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
kernel/sched/membarrier.c +1 -3
@@ -471,9 +471,7 @@ static int sync_runqueues_membarrier_sta }rcu_read_unlock (); -preempt_disable (); -smp_call_function_many (tmpmask, ipi_sync_rq_state, mm,1 ); -preempt_enable (); +on_each_cpu_mask (tmpmask, ipi_sync_rq_state, mm, true);free_cpumask_var (tmpmask);cpus_read_unlock ();
[email protected]
maintainerPATCH 274/306 sched: Collate affine_move_task() stoppers
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Peter Zijlstra <[email protected]>
commit 58b1a45086b5f80f2b2842aa7ed0da51a64a302b upstream.
The SCA_MIGRATE_ENABLE and task_running() cases are almost identical, collapse them to avoid further duplication.
--- kernel/sched/core.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-)
kernel/sched/core.c +8 -15
@@ -2279,30 +2279,23 @@ static int affine_move_task(struct rq *rreturn -EINVAL ; } -if (flags &SCA_MIGRATE_ENABLE ) { - -refcount_inc (&pending->refs);/* pending->{arg,stop_work} */ - p->migration_flags &= ~MDF_PUSH ; -task_rq_unlock (rq, p, rf); - -stop_one_cpu_nowait (cpu_of (rq), migration_cpu_stop, - &pending->arg, &pending->stop_work); - -return 0 ; - } -if (task_running (rq, p) || p->state ==TASK_WAKING ) {/* -* Lessen races (and headaches) by delegating -* is_migration_disabled(p) checks to the stopper, which will -* run on the same CPU as said p. +* MIGRATE_ENABLE gets here because 'p == current', but for +* anything else we cannot do is_migration_disabled(), punt +* and have the stopper function handle it all race-free. */ +refcount_inc (&pending->refs);/* pending->{arg,stop_work} */ +if (flags &SCA_MIGRATE_ENABLE ) + p->migration_flags &= ~MDF_PUSH ;task_rq_unlock (rq, p, rf);stop_one_cpu_nowait (cpu_of (rq), migration_cpu_stop, &pending->arg, &pending->stop_work); +if (flags &SCA_MIGRATE_ENABLE ) +return 0 ; }else {if (!is_migration_disabled (p)) {
[email protected]
maintainerPATCH 275/306 sched: Simplify migration_cpu_stop()
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Peter Zijlstra <[email protected]>
commit c20cf065d4a619d394d23290093b1002e27dff86 upstream.
When affine_move_task() issues a migration_cpu_stop(), the purpose of that function is to complete that @pending, not any random other p->migration_pending that might have gotten installed since.
This realization much simplifies migration_cpu_stop() and allows further necessary steps to fix all this as it provides the guarantee that @pending's stopper will complete @pending (and not some random other @pending).
--- kernel/sched/core.c | 56 +++++++--------------------------------------------- 1 file changed, 8 insertions(+), 48 deletions(-)
kernel/sched/core.c +8 -48
@@ -1898,8 +1898,8 @@ static struct rq *__migrate_task(struct*/ static int migration_cpu_stop (void *data) { -struct set_affinity_pending *pending;struct migration_arg *arg = data; +struct set_affinity_pending *pending = arg->pending;struct task_struct *p = arg->task;int dest_cpu = arg->dest_cpu;struct rq *rq =this_rq ();
@@ -1921,25 +1921,6 @@ static int migration_cpu_stop(void *dataraw_spin_lock (&p->pi_lock);rq_lock (rq, &rf); - pending = p->migration_pending; -if (pending && !arg->pending) { -/* -* This happens from sched_exec() and migrate_task_to(), -* neither of them care about pending and just want a task to -* maybe move about. -* -* Even if there is a pending, we can ignore it, since -* affine_move_task() will have it's own stop_work's in flight -* which will manage the completion. -* -* Notably, pending doesn't need to match arg->pending. This can -* happen when tripple concurrent affine_move_task() first sets -* pending, then clears pending and eventually sets another -* pending. -*/ - pending =NULL ; - } -/* * If task_rq(p) != rq, it cannot be migrated here, because we're * holding rq->lock, if p->on_rq == 0 it cannot get enqueued because
@@ -1950,31 +1931,20 @@ static int migration_cpu_stop(void *data goto out;if (pending) { - p->migration_pending =NULL ; +if (p->migration_pending == pending) + p->migration_pending =NULL ; complete = true; } -/* migrate_enable() -- we must not race against SCA */ -if (dest_cpu <0 ) { -/* -* When this was migrate_enable() but we no longer -* have a @pending, a concurrent SCA 'fixed' things -* and we should be valid again. Nothing to do. -*/ -if (!pending) { -WARN_ON_ONCE (!cpumask_test_cpu (task_cpu (p), &p->cpus_mask)); - goto out; - } - +if (dest_cpu <0 ) dest_cpu =cpumask_any_distribute (&p->cpus_mask); - }if (task_on_rq_queued (p)) rq =__migrate_task (rq, &rf, p, dest_cpu);else p->wake_cpu = dest_cpu; - }else if (dest_cpu <0 || pending) { + }else if (pending) {/* * This happens when we get migrated between migrate_enable()'s * preempt_enable() and scheduling the stopper task. At that
@@ -1989,23 +1959,14 @@ static int migration_cpu_stop(void *data* ->pi_lock, so the allowed mask is stable - if it got * somewhere allowed, we're done. */ -if (pending &&cpumask_test_cpu (task_cpu (p), p->cpus_ptr)) { - p->migration_pending =NULL ; +if (cpumask_test_cpu (task_cpu (p), p->cpus_ptr)) { +if (p->migration_pending == pending) + p->migration_pending =NULL ; complete = true; goto out; }/* -* When this was migrate_enable() but we no longer have an -* @pending, a concurrent SCA 'fixed' things and we should be -* valid again. Nothing to do. -*/ -if (!pending) { -WARN_ON_ONCE (!cpumask_test_cpu (task_cpu (p), &p->cpus_mask)); - goto out; - } - -/* * When migrate_enable() hits a rq mis-match we can't reliably * determine is_migration_disabled() and so have to chase after * it.
@@ -2022,7 +1983,6 @@ out:complete_all (&pending->done);/* For pending->{arg,stop_work} */ - pending = arg->pending;if (pending &&refcount_dec_and_test (&pending->refs))wake_up_var (&pending->refs);
[email protected]
maintainerPATCH 276/306 sched: Optimize migration_cpu_stop()
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Peter Zijlstra <[email protected]>
commit 3f1bc119cd7fc987c8ed25ffb717f99403bb308c upstream.
When the purpose of migration_cpu_stop() is to migrate the task to 'any' valid CPU, don't migrate the task when it's already running on a valid CPU.
--- kernel/sched/core.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
kernel/sched/core.c +12 -1
@@ -1936,14 +1936,25 @@ static int migration_cpu_stop(void *data complete = true; } -if (dest_cpu <0 ) +if (dest_cpu <0 ) { +if (cpumask_test_cpu (task_cpu (p), &p->cpus_mask)) + goto out; + dest_cpu =cpumask_any_distribute (&p->cpus_mask); + }if (task_on_rq_queued (p)) rq =__migrate_task (rq, &rf, p, dest_cpu);else p->wake_cpu = dest_cpu; +/* +* XXX __migrate_task() can fail, at which point we might end +* up running on a dodgy CPU, AFAICT this can only happen +* during CPU hotplug, at which point we'll get pushed out +* anyway, so it's probably not a big deal. +*/ + }else if (pending) {/* * This happens when we get migrated between migrate_enable()'s
[email protected]
maintainerPATCH 277/306 sched: Fix affine_move_task() self-concurrency
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Peter Zijlstra <[email protected]>
commit 9e81889c7648d48dd5fe13f41cbc99f3c362484a upstream.
Consider:
sched_setaffinity(p, X); sched_setaffinity(p, Y);
Then the first will install p->migration_pending = &my_pending; and issue stop_one_cpu_nowait(pending); and the second one will read p->migration_pending and _also_ issue: stop_one_cpu_nowait(pending), the _SAME_ @pending.
This causes stopper list corruption.
Add set_affinity_pending::stop_pending, to indicate if a stopper is in progress.
--- kernel/sched/core.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
kernel/sched/core.c +12 -3
@@ -1864,6 +1864,7 @@ struct migration_arg {struct set_affinity_pending {refcount_t refs; +unsigned int stop_pending;struct completion done;struct cpu_stop_work stop_work;struct migration_arg arg;
@@ -1982,12 +1983,15 @@ static int migration_cpu_stop(void *data* determine is_migration_disabled() and so have to chase after * it. */ +WARN_ON_ONCE (!pending->stop_pending);task_rq_unlock (rq, p, &rf);stop_one_cpu_nowait (task_cpu (p), migration_cpu_stop, &pending->arg, &pending->stop_work);return 0 ; } out: +if (pending) + pending->stop_pending = false;task_rq_unlock (rq, p, &rf);if (complete)
@@ -2183,7 +2187,7 @@ static int affine_move_task(struct rq *r int dest_cpu, unsigned int flags) {struct set_affinity_pending my_pending = { }, *pending =NULL ; -bool complete = false; +bool stop_pending, complete = false;/* Can the task run on the task's current CPU? If so, we're done */ if (cpumask_test_cpu (task_cpu (p), &p->cpus_mask)) {
@@ -2256,14 +2260,19 @@ static int affine_move_task(struct rq *r* anything else we cannot do is_migration_disabled(), punt * and have the stopper function handle it all race-free. */ + stop_pending = pending->stop_pending; +if (!stop_pending) + pending->stop_pending = true;refcount_inc (&pending->refs);/* pending->{arg,stop_work} */ if (flags &SCA_MIGRATE_ENABLE ) p->migration_flags &= ~MDF_PUSH ;task_rq_unlock (rq, p, rf); -stop_one_cpu_nowait (cpu_of (rq), migration_cpu_stop, - &pending->arg, &pending->stop_work); +if (!stop_pending) { +stop_one_cpu_nowait (cpu_of (rq), migration_cpu_stop, + &pending->arg, &pending->stop_work); + }if (flags &SCA_MIGRATE_ENABLE )return 0 ;
[email protected]
maintainerPATCH 278/306 sched: Simplify set_affinity_pending refcounts
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Peter Zijlstra <[email protected]>
commit 50caf9c14b1498c90cf808dbba2ca29bd32ccba4 upstream.
Now that we have set_affinity_pending::stop_pending to indicate if a stopper is in progress, and we have the guarantee that if that stopper exists, it will (eventually) complete our @pending we can simplify the refcount scheme by no longer counting the stopper thread.
--- kernel/sched/core.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-)
kernel/sched/core.c +20 -12
@@ -1862,6 +1862,10 @@ struct migration_arg {struct set_affinity_pending *pending; }; +/* +* @refs: number of wait_for_completion() +* @stop_pending: is @stop_work in use +*/ struct set_affinity_pending {refcount_t refs;unsigned int stop_pending;
@@ -1997,10 +2001,6 @@ out:if (complete)complete_all (&pending->done); -/* For pending->{arg,stop_work} */ -if (pending &&refcount_dec_and_test (&pending->refs)) -wake_up_var (&pending->refs); -return 0 ; }
@@ -2199,12 +2199,16 @@ static int affine_move_task(struct rq *r push_task =get_task_struct (p); } +/* +* If there are pending waiters, but no pending stop_work, +* then complete now. +*/ pending = p->migration_pending; -if (pending) { -refcount_inc (&pending->refs); +if (pending && !pending->stop_pending) { p->migration_pending =NULL ; complete = true; } +task_rq_unlock (rq, p, rf);if (push_task) {
@@ -2213,7 +2217,7 @@ static int affine_move_task(struct rq *r }if (complete) - goto do_complete; +complete_all (&pending->done);return 0 ; }
@@ -2264,9 +2268,9 @@ static int affine_move_task(struct rq *rif (!stop_pending) pending->stop_pending = true; -refcount_inc (&pending->refs);/* pending->{arg,stop_work} */ if (flags &SCA_MIGRATE_ENABLE ) p->migration_flags &= ~MDF_PUSH ; +task_rq_unlock (rq, p, rf);if (!stop_pending) {
@@ -2282,12 +2286,13 @@ static int affine_move_task(struct rq *rif (task_on_rq_queued (p)) rq =move_queued_task (rq, rf, p, dest_cpu); - p->migration_pending =NULL ; - complete = true; +if (!pending->stop_pending) { + p->migration_pending =NULL ; + complete = true; + } }task_rq_unlock (rq, p, rf); -do_complete:if (complete)complete_all (&pending->done); }
@@ -2295,7 +2300,7 @@ do_complete:wait_for_completion (&pending->done);if (refcount_dec_and_test (&pending->refs)) -wake_up_var (&pending->refs); +wake_up_var (&pending->refs);/* No UaF, just an address */ /* * Block the original owner of &pending until all subsequent callers
@@ -2303,6 +2308,9 @@ do_complete:*/ wait_var_event (&my_pending.refs, !refcount_read (&my_pending.refs)); +/* ARGH */ +WARN_ON_ONCE (my_pending.stop_pending); +return 0 ; }
[email protected]
maintainerPATCH 279/306 efi: stub: omit SetVirtualAddressMap() if marked unsupported in RT_PROP table
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Ard Biesheuvel <[email protected]>
commit 9e9888a0fe97b9501a40f717225d2bef7100a2c1 upstream.
The EFI_RT_PROPERTIES_TABLE contains a mask of runtime services that are available after ExitBootServices(). This mostly does not concern the EFI stub at all, given that it runs before that. However, there is one call that is made at runtime, which is the call to SetVirtualAddressMap() (which is not even callable at boot time to begin with)
So add the missing handling of the RT_PROP table to ensure that we only call SetVirtualAddressMap() if it is not being advertised as unsupported by the firmware.
--- drivers/firmware/efi/libstub/efi-stub.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
drivers/firmware/efi/libstub/efi-stub.c +16 -0
@@ -96,6 +96,18 @@ static void install_memreserve_table(voiefi_err ("Failed to install memreserve config table!\n" ); } +static u32 get_supported_rt_services (void ) +{ +const efi_rt_properties_table_t *rt_prop_table; +u32 supported =EFI_RT_SUPPORTED_ALL ; + + rt_prop_table =get_efi_config_table (EFI_RT_PROPERTIES_TABLE_GUID ); +if (rt_prop_table) + supported &= rt_prop_table->runtime_services_supported; + +return supported; +} +/* * EFI entry point for the arm/arm64 EFI stubs. This is the entrypoint * that is described in the PE/COFF header. Most of the code is the same
@@ -250,6 +262,10 @@ efi_status_t __efiapi efi_pe_entry(efi_h (prop_tbl->memory_protection_attribute &EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA ); +/* force efi_novamap if SetVirtualAddressMap() is unsupported */ + efi_novamap |= !(get_supported_rt_services () & +EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP ); +/* hibernation expects the runtime regions to stay in the same place */ if (!IS_ENABLED (CONFIG_HIBERNATION ) && !efi_nokaslr && !flat_va_mapping) {/*
[email protected]
maintainerPATCH 280/306 powerpc/64s: Fix instruction encoding for lis in ppc_function_entry()
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Naveen N. Rao <[email protected]>
commit cea15316ceee2d4a51dfdecd79e08a438135416c upstream.
'lis r2,N' is 'addis r2,0,N' and the instruction encoding in the macro LIS_R2 is incorrect (it currently maps to 'addis r0,r2,N'). Fix the same.
--- arch/powerpc/include/asm/code-patching.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/include/asm/code-patching.h +1 -1
@@ -73,7 +73,7 @@ void __patch_exception(int exc, unsigned#endif #define OP_RT_RA_MASK 0xffff0000UL -#define LIS_R2 0x3c020000UL +#define LIS_R2 0x3c400000UL#define ADDIS_R2_R12 0x3c4c0000UL#define ADDI_R2_R2 0x38420000UL
[email protected]
maintainerPATCH 281/306 powerpc: Fix inverted SET_FULL_REGS bitop
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Nicholas Piggin <[email protected]>
commit 73ac79881804eed2e9d76ecdd1018037f8510cb1 upstream.
This bit operation was inverted and set the low bit rather than cleared it, breaking the ability to ptrace non-volatile GPRs after exec. Fix.
Only affects 64e and 32-bit.
--- arch/powerpc/include/asm/ptrace.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/powerpc/include/asm/ptrace.h +2 -2
@@ -195,7 +195,7 @@ static inline void regs_set_return_value#define TRAP_FLAGS_MASK 0x11#define TRAP (regs) ((regs)->trap & ~TRAP_FLAGS_MASK)#define FULL_REGS (regs) (((regs)->trap & 1) == 0) -#define SET_FULL_REGS (regs) ((regs)->trap |= 1) +#define SET_FULL_REGS (regs) ((regs)->trap &= ~1)#endif #define CHECK_FULL_REGS (regs) BUG_ON(!FULL_REGS(regs))#define NV_REG_POISON 0xdeadbeefdeadbeefUL
@@ -210,7 +210,7 @@ static inline void regs_set_return_value#define TRAP_FLAGS_MASK 0x1F#define TRAP (regs) ((regs)->trap & ~TRAP_FLAGS_MASK)#define FULL_REGS (regs) (((regs)->trap & 1) == 0) -#define SET_FULL_REGS (regs) ((regs)->trap |= 1) +#define SET_FULL_REGS (regs) ((regs)->trap &= ~1)#define IS_CRITICAL_EXC (regs) (((regs)->trap & 2) != 0)#define IS_MCHECK_EXC (regs) (((regs)->trap & 4) != 0)#define IS_DEBUG_EXC (regs) (((regs)->trap & 8) != 0)
[email protected]
maintainerPATCH 282/306 powerpc: Fix missing declaration of [en/dis]able_kernel_vsx()
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Christophe Leroy <[email protected]>
commit bd73758803c2eedc037c2268b65a19542a832594 upstream.
Add stub instances of enable_kernel_vsx() and disable_kernel_vsx() when CONFIG_VSX is not set, to avoid following build failure.
CC [M] drivers/gpu/drm/amd/amdgpu/../display/dc/calcs/dcn_calcs.o
In file included from ./drivers/gpu/drm/amd/amdgpu/../display/dc/dm_services_types.h:29,
from ./drivers/gpu/drm/amd/amdgpu/../display/dc/dm_services.h:37,
from drivers/gpu/drm/amd/amdgpu/../display/dc/calcs/dcn_calcs.c:27:
drivers/gpu/drm/amd/amdgpu/../display/dc/calcs/dcn_calcs.c: In function 'dcn_bw_apply_registry_override':
./drivers/gpu/drm/amd/amdgpu/../display/dc/os_types.h:64:3: error: implicit declaration of function 'enable_kernel_vsx'; did you mean 'enable_kernel_fp'? [-Werror=implicit-function-declaration]
64 | enable_kernel_vsx(); \
| ^~~~~~~~~~~~~~~~~
drivers/gpu/drm/amd/amdgpu/../display/dc/calcs/dcn_calcs.c:640:2: note: in expansion of macro 'DC_FP_START'
640 | DC_FP_START();
| ^~~~~~~~~~~
./drivers/gpu/drm/amd/amdgpu/../display/dc/os_types.h:75:3: error: implicit declaration of function 'disable_kernel_vsx'; did you mean 'disable_kernel_fp'? [-Werror=implicit-function-declaration]
75 | disable_kernel_vsx(); \
| ^~~~~~~~~~~~~~~~~~
drivers/gpu/drm/amd/amdgpu/../display/dc/calcs/dcn_calcs.c:676:2: note: in expansion of macro 'DC_FP_END'
676 | DC_FP_END();
| ^~~~~~~~~ cc1: some warnings being treated as errors
make[5]: *** [drivers/gpu/drm/amd/amdgpu/../display/dc/calcs/dcn_calcs.o] Error 1
This works because the caller is checking if VSX is available using cpu_has_feature():
#define DC_FP_START() { \
if (cpu_has_feature(CPU_FTR_VSX_COMP)) { \
preempt_disable(); \
enable_kernel_vsx(); \
} else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP)) { \
preempt_disable(); \
enable_kernel_altivec(); \
} else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE)) { \
preempt_disable(); \
enable_kernel_fp(); \
} \When CONFIG_VSX is not selected, cpu_has_feature(CPU_FTR_VSX_COMP) constant folds to 'false' so the call to enable_kernel_vsx() is discarded and the build succeeds.
--- arch/powerpc/include/asm/switch_to.h | 10 ++++++++++ 1 file changed, 10 insertions(+)
arch/powerpc/include/asm/switch_to.h +10 -0
@@ -71,6 +71,16 @@ static inline void disable_kernel_vsx(vo {msr_check_and_clear (MSR_FP |MSR_VEC |MSR_VSX ); } +#else +static inline void enable_kernel_vsx (void ) +{ +BUILD_BUG (); +} + +static inline void disable_kernel_vsx (void ) +{ +BUILD_BUG (); +}#endif #ifdef CONFIG_SPE
[email protected]
maintainerPATCH 283/306 binfmt_misc: fix possible deadlock in bm_register_write
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Lior Ribak <[email protected]>
commit e7850f4d844e0acfac7e570af611d89deade3146 upstream.
There is a deadlock in bm_register_write:
First, in the begining of the function, a lock is taken on the binfmt_misc root inode with inode_lock(d_inode(root)).
Then, if the user used the MISC_FMT_OPEN_FILE flag, the function will call open_exec on the user-provided interpreter.
open_exec will call a path lookup, and if the path lookup process includes the root of binfmt_misc, it will try to take a shared lock on its inode again, but it is already locked, and the code will get stuck in a deadlock
To reproduce the bug:
$ echo ":iiiii:E::ii::/proc/sys/fs/binfmt_misc/bla:F" > /proc/sys/fs/binfmt_misc/register
backtrace of where the lock occurs (#5):
0 schedule () at ./arch/x86/include/asm/current.h:15 1 0xffffffff81b51237 in rwsem_down_read_slowpath (sem=0xffff888003b202e0, count=<optimized out>, state=state@entry=2) at kernel/locking/rwsem.c:992 2 0xffffffff81b5150a in __down_read_common (state=2, sem=<optimized out>) at kernel/locking/rwsem.c:1213 3 __down_read (sem=<optimized out>) at kernel/locking/rwsem.c:1222 4 down_read (sem=<optimized out>) at kernel/locking/rwsem.c:1355 5 0xffffffff811ee22a in inode_lock_shared (inode=<optimized out>) at ./include/linux/fs.h:783 6 open_last_lookups (op=0xffffc9000022fe34, file=0xffff888004098600, nd=0xffffc9000022fd10) at fs/namei.c:3177 7 path_openat (nd=nd@entry=0xffffc9000022fd10, op=op@entry=0xffffc9000022fe34, flags=flags@entry=65) at fs/namei.c:3366 8 0xffffffff811efe1c in do_filp_open (dfd=<optimized out>, pathname=pathname@entry=0xffff8880031b9000, op=op@entry=0xffffc9000022fe34) at fs/namei.c:3396 9 0xffffffff811e493f in do_open_execat (fd=fd@entry=-100, name=name@entry=0xffff8880031b9000, flags=<optimized out>, flags@entry=0) at fs/exec.c:913
10 0xffffffff811e4a92 in open_exec (name=<optimized out>) at fs/exec.c:948
11 0xffffffff8124aa84 in bm_register_write (file=<optimized out>, buffer=<optimized out>, count=19, ppos=<optimized out>) at fs/binfmt_misc.c:682 12 0xffffffff811decd2 in vfs_write (file=file@entry=0xffff888004098500, buf=buf@entry=0xa758d0 ":iiiii:E::ii::i:CF
", count=count@entry=19, pos=pos@entry=0xffffc9000022ff10) at fs/read_write.c:603
13 0xffffffff811defda in ksys_write (fd=<optimized out>, buf=0xa758d0 ":iiiii:E::ii::i:CF
", count=19) at fs/read_write.c:658
14 0xffffffff81b49813 in do_syscall_64 (nr=<optimized out>, regs=0xffffc9000022ff58) at arch/x86/entry/common.c:46
15 0xffffffff81c0007c in entry_SYSCALL_64 () at arch/x86/entry/entry_64.S:120
To solve the issue, the open_exec call is moved to before the write lock is taken by bm_register_write
--- fs/binfmt_misc.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-)
fs/binfmt_misc.c +14 -15
@@ -647,12 +647,24 @@ static ssize_t bm_register_write(structstruct super_block *sb =file_inode (file)->i_sb;struct dentry *root = sb->s_root, *dentry;int err =0 ; +struct file *f =NULL ; e =create_entry (buffer, count);if (IS_ERR (e))return PTR_ERR (e); +if (e->flags &MISC_FMT_OPEN_FILE ) { + f =open_exec (e->interpreter); +if (IS_ERR (f)) { +pr_notice ("register: failed to install interpreter file %s\n" , + e->interpreter); +kfree (e); +return PTR_ERR (f); + } + e->interp_file = f; + } +inode_lock (d_inode (root)); dentry =lookup_one_len (e->name, root,strlen (e->name)); err =PTR_ERR (dentry);
@@ -676,21 +688,6 @@ static ssize_t bm_register_write(struct goto out2; } -if (e->flags &MISC_FMT_OPEN_FILE ) { -struct file *f; - - f =open_exec (e->interpreter); -if (IS_ERR (f)) { - err =PTR_ERR (f); -pr_notice ("register: failed to install interpreter file %s\n" , e->interpreter); -simple_release_fs (&bm_mnt, &entry_count); -iput (inode); - inode =NULL ; - goto out2; - } - e->interp_file = f; - } - e->dentry =dget (dentry); inode->i_private = e; inode->i_fop = &bm_entry_operations;
@@ -707,6 +704,8 @@ out:inode_unlock (d_inode (root));if (err) { +if (f) +filp_close (f,NULL );kfree (e);return err; }
[email protected]
maintainerPATCH 284/306 kasan, mm: fix crash with HW_TAGS and DEBUG_PAGEALLOC
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Andrey Konovalov <[email protected]>
commit f9d79e8dce4077d3c6ab739c808169dfa99af9ef upstream.
Currently, kasan_free_nondeferred_pages()->kasan_free_pages() is called after debug_pagealloc_unmap_pages(). This causes a crash when debug_pagealloc is enabled, as HW_TAGS KASAN can't set tags on an unmapped page.
This patch puts kasan_free_nondeferred_pages() before debug_pagealloc_unmap_pages() and arch_free_page(), which can also make the page unavailable.
--- mm/page_alloc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
mm/page_alloc.c +6 -2
@@ -1282,6 +1282,12 @@ static __always_inline bool free_pages_pkernel_poison_pages (page,1 << order);/* +* With hardware tag-based KASAN, memory tags must be set before the +* page becomes unavailable via debug_pagealloc or arch_free_page. +*/ +kasan_free_nondeferred_pages (page, order); + +/* * arch_free_page() can make the page's contents inaccessible. s390 * does this. So nothing which can access the page's contents should * happen after this.
@@ -1290,8 +1296,6 @@ static __always_inline bool free_pages_pdebug_pagealloc_unmap_pages (page,1 << order); -kasan_free_nondeferred_pages (page, order); -return true; }
[email protected]
maintainerPATCH 285/306 kasan: fix KASAN_STACK dependency for HW_TAGS
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Andrey Konovalov <[email protected]>
commit d9b571c885a8974fbb7d4ee639dbc643fd000f9e upstream.
There's a runtime failure when running HW_TAGS-enabled kernel built with GCC on hardware that doesn't support MTE. GCC-built kernels always have CONFIG_KASAN_STACK enabled, even though stack instrumentation isn't supported by HW_TAGS. Having that config enabled causes KASAN to issue MTE-only instructions to unpoison kernel stacks, which causes the failure.
Fix the issue by disallowing CONFIG_KASAN_STACK when HW_TAGS is used.
(The commit that introduced CONFIG_KASAN_HW_TAGS specified proper
dependency for CONFIG_KASAN_STACK_ENABLE but not for CONFIG_KASAN_STACK.)
--- lib/Kconfig.kasan | 1 + 1 file changed, 1 insertion(+)
lib/Kconfig.kasan +1 -0
@@ -156,6 +156,7 @@ config KASAN_STACK_ENABLE config KASAN_STACK int + depends on KASAN_GENERIC || KASAN_SW_TAGS default 1 if KASAN_STACK_ENABLE || CC_IS_GCC default 0
[email protected]
maintainerPATCH 286/306 x86/unwind/orc: Disable KASAN checking in the ORC unwinder, part 2
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Josh Poimboeuf <[email protected]>
commit e504e74cc3a2c092b05577ce3e8e013fae7d94e6 upstream.
KASAN reserves "redzone" areas between stack frames in order to detect stack overruns. A read or write to such an area triggers a KASAN "stack-out-of-bounds" BUG.
Normally, the ORC unwinder stays in-bounds and doesn't access the redzone. But sometimes it can't find ORC metadata for a given instruction. This can happen for code which is missing ORC metadata, or for generated code. In such cases, the unwinder attempts to fall back to frame pointers, as a best-effort type thing.
This fallback often works, but when it doesn't, the unwinder can get confused and go off into the weeds into the KASAN redzone, triggering the aforementioned KASAN BUG.
But in this case, the unwinder's confusion is actually harmless and working as designed. It already has checks in place to prevent off-stack accesses, but those checks get short-circuited by the KASAN BUG. And a BUG is a lot more disruptive than a harmless unwinder warning.
Disable the KASAN checks by using READ_ONCE_NOCHECK() for all stack accesses. This finishes the job started by commit 881125bfe65b ("x86/unwind: Disable KASAN checking in the ORC unwinder"), which only partially fixed the issue.
--- arch/x86/kernel/unwind_orc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
arch/x86/kernel/unwind_orc.c +6 -6
@@ -367,8 +367,8 @@ static bool deref_stack_regs(struct unwiif (!stack_access_ok (state, addr,sizeof (struct pt_regs )))return false; - *ip = regs->ip; - *sp = regs->sp; + *ip =READ_ONCE_NOCHECK (regs->ip); + *sp =READ_ONCE_NOCHECK (regs->sp);return true; }
@@ -380,8 +380,8 @@ static bool deref_stack_iret_regs(structif (!stack_access_ok (state, addr,IRET_FRAME_SIZE ))return false; - *ip = regs->ip; - *sp = regs->sp; + *ip =READ_ONCE_NOCHECK (regs->ip); + *sp =READ_ONCE_NOCHECK (regs->sp);return true; }
@@ -402,12 +402,12 @@ static bool get_reg(struct unwind_statereturn false;if (state->full_regs) { - *val = ((unsigned long *)state->regs)[reg]; + *val =READ_ONCE_NOCHECK (((unsigned long *)state->regs)[reg]);return true; }if (state->prev_regs) { - *val = ((unsigned long *)state->prev_regs)[reg]; + *val =READ_ONCE_NOCHECK (((unsigned long *)state->prev_regs)[reg]);return true; }
[email protected]
maintainerPATCH 287/306 x86/sev-es: Introduce ip_within_syscall_gap() helper
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Joerg Roedel <[email protected]>
commit 78a81d88f60ba773cbe890205e1ee67f00502948 upstream.
Introduce a helper to check whether an exception came from the syscall gap and use it in the SEV-ES code. Extend the check to also cover the compatibility SYSCALL entry path.
--- arch/x86/entry/entry_64_compat.S | 2 ++ arch/x86/include/asm/proto.h | 1 + arch/x86/include/asm/ptrace.h | 15 +++++++++++++++ arch/x86/kernel/traps.c | 3 +-- 4 files changed, 19 insertions(+), 2 deletions(-)
arch/x86/entry/entry_64_compat.S +2 -0
@@ -210,6 +210,8 @@ SYM_CODE_START(entry_SYSCALL_compat) /* Switch to the kernel stack */ movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp +SYM_INNER_LABEL(entry_SYSCALL_compat_safe_stack, SYM_L_GLOBAL) + /* Construct struct pt_regs on stack */ pushq $__USER32_DS /* pt_regs->ss */ pushq %r8 /* pt_regs->sp */
arch/x86/include/asm/proto.h +1 -0
@@ -25,6 +25,7 @@ void __end_SYSENTER_singlestep_region(vovoid entry_SYSENTER_compat (void );void __end_entry_SYSENTER_compat (void );void entry_SYSCALL_compat (void ); +void entry_SYSCALL_compat_safe_stack (void );void entry_INT80_compat (void );#ifdef CONFIG_XEN_PV void xen_entry_INT80_compat (void );
arch/x86/include/asm/ptrace.h +15 -0
@@ -94,6 +94,8 @@ struct pt_regs {#include <asm/paravirt_types.h> #endif +#include <asm/proto.h> +struct cpuinfo_x86 ;struct task_struct ;
@@ -175,6 +177,19 @@ static inline bool any_64bit_mode(struct#ifdef CONFIG_X86_64 #define current_user_stack_pointer () current_pt_regs()->sp#define compat_user_stack_pointer () current_pt_regs()->sp + +static inline bool ip_within_syscall_gap (struct pt_regs *regs) +{ +bool ret = (regs->ip >= (unsigned long )entry_SYSCALL_64 && + regs->ip < (unsigned long )entry_SYSCALL_64_safe_stack); + +#ifdef CONFIG_IA32_EMULATION + ret = ret || (regs->ip >= (unsigned long )entry_SYSCALL_compat && + regs->ip < (unsigned long )entry_SYSCALL_compat_safe_stack); +#endif + +return ret; +}#endif static inline unsigned long kernel_stack_pointer (struct pt_regs *regs)
arch/x86/kernel/traps.c +1 -2
@@ -694,8 +694,7 @@ asmlinkage __visible noinstr struct pt_r* In the SYSCALL entry path the RSP value comes from user-space - don't * trust it and switch to the current kernel stack */ -if (regs->ip >= (unsigned long )entry_SYSCALL_64 && - regs->ip < (unsigned long )entry_SYSCALL_64_safe_stack) { +if (ip_within_syscall_gap (regs)) { sp =this_cpu_read (cpu_current_top_of_stack); goto sync; }
[email protected]
maintainerPATCH 288/306 x86/sev-es: Check regs->sp is trusted before adjusting #VC IST stack
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Joerg Roedel <[email protected]>
commit 545ac14c16b5dbd909d5a90ddf5b5a629a40fa94 upstream.
The code in the NMI handler to adjust the #VC handler IST stack is needed in case an NMI hits when the #VC handler is still using its IST stack.
But the check for this condition also needs to look if the regs->sp value is trusted, meaning it was not set by user-space. Extend the check to not use regs->sp when the NMI interrupted user-space code or the SYSCALL gap.
--- arch/x86/kernel/sev-es.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
arch/x86/kernel/sev-es.c +12 -2
@@ -121,8 +121,18 @@ static void __init setup_vc_stacks(int ccea_set_pte ((void *)vaddr, pa,PAGE_KERNEL ); } -static __always_inline bool on_vc_stack(unsigned long sp) +static __always_inline bool on_vc_stack(struct pt_regs *regs) { +unsigned long sp = regs->sp; + +/* User-mode RSP is not trusted */ +if (user_mode (regs)) +return false; + +/* SYSCALL gap still has user-mode RSP */ +if (ip_within_syscall_gap (regs)) +return false; +return ((sp >=__this_cpu_ist_bottom_va (VC )) && (sp <__this_cpu_ist_top_va (VC ))); }
@@ -144,7 +154,7 @@ void noinstr __sev_es_ist_enter(struct p old_ist =__this_cpu_read (cpu_tss_rw.x86_tss.ist[IST_INDEX_VC ]);/* Make room on the IST stack */ -if (on_vc_stack (regs->sp)) +if (on_vc_stack (regs)) new_ist =ALIGN_DOWN (regs->sp,8 ) -sizeof (old_ist);else new_ist = old_ist -sizeof (old_ist);
[email protected]
maintainerPATCH 289/306 x86/sev-es: Correctly track IRQ states in runtime #VC handler
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Joerg Roedel <[email protected]>
commit 62441a1fb53263bda349b6e5997c3cc5c120d89e upstream.
Call irqentry_nmi_enter()/irqentry_nmi_exit() in the #VC handler to correctly track the IRQ state during its execution.
--- arch/x86/kernel/sev-es.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
arch/x86/kernel/sev-es.c +4 -2
@@ -1258,13 +1258,12 @@ static __always_inline bool on_vc_fallbaDEFINE_IDTENTRY_VC_SAFE_STACK (exc_vmm_communication) {struct sev_es_runtime_data *data =this_cpu_read (runtime_data); +irqentry_state_t irq_state;struct ghcb_state state;struct es_em_ctxt ctxt;enum es_result result;struct ghcb *ghcb; -lockdep_assert_irqs_disabled (); -/* * Handle #DB before calling into !noinstr code to avoid recursive #DB. */
@@ -1273,6 +1272,8 @@ DEFINE_IDTENTRY_VC_SAFE_STACK(exc_vmm_coreturn ; } + irq_state =irqentry_nmi_enter (regs); +lockdep_assert_irqs_disabled ();instrumentation_begin ();/*
@@ -1335,6 +1336,7 @@ DEFINE_IDTENTRY_VC_SAFE_STACK(exc_vmm_co out:instrumentation_end (); +irqentry_nmi_exit (regs, irq_state);return ;
[email protected]
maintainerPATCH 290/306 x86/sev-es: Use __copy_from_user_inatomic()
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Joerg Roedel <[email protected]>
commit bffe30dd9f1f3b2608a87ac909a224d6be472485 upstream.
The #VC handler must run in atomic context and cannot sleep. This is a problem when it tries to fetch instruction bytes from user-space via copy_from_user().
Introduce a insn_fetch_from_user_inatomic() helper which uses __copy_from_user_inatomic() to safely copy the instruction bytes to kernel memory in the #VC handler.
--- arch/x86/include/asm/insn-eval.h | 2 + arch/x86/kernel/sev-es.c | 2 - arch/x86/lib/insn-eval.c | 66 ++++++++++++++++++++++++++++++--------- 3 files changed, 55 insertions(+), 15 deletions(-)
arch/x86/include/asm/insn-eval.h +2 -0
@@ -23,6 +23,8 @@ unsigned long insn_get_seg_base(struct pint insn_get_code_seg_params (struct pt_regs *regs);int insn_fetch_from_user (struct pt_regs *regs,unsigned char buf[MAX_INSN_SIZE ]); +int insn_fetch_from_user_inatomic (struct pt_regs *regs, +unsigned char buf[MAX_INSN_SIZE ]);bool insn_decode (struct insn *insn,struct pt_regs *regs,unsigned char buf[MAX_INSN_SIZE ],int buf_size);
arch/x86/kernel/sev-es.c +1 -1
@@ -258,7 +258,7 @@ static enum es_result vc_decode_insn(strint res;if (user_mode (ctxt->regs)) { - res =insn_fetch_from_user (ctxt->regs, buffer); + res =insn_fetch_from_user_inatomic (ctxt->regs, buffer);if (!res) { ctxt->fi.vector =X86_TRAP_PF ; ctxt->fi.error_code =X86_PF_INSTR |X86_PF_USER ;
arch/x86/lib/insn-eval.c +52 -14
82 lines not on this page · raw message
[email protected]
maintainerPATCH 291/306 x86/entry: Fix entry/exit mismatch on failed fast 32-bit syscalls
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Andy Lutomirski <[email protected]>
commit 5d5675df792ff67e74a500c4c94db0f99e6a10ef upstream.
On a 32-bit fast syscall that fails to read its arguments from user memory, the kernel currently does syscall exit work but not syscall entry work. This confuses audit and ptrace. For example:
$ ./tools/testing/selftests/x86/syscall_arg_fault_32
...
strace: pid 264258: entering, ptrace_syscall_info.op == 2
...This is a minimal fix intended for ease of backporting. A more complete cleanup is coming.
--- arch/x86/entry/common.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
arch/x86/entry/common.c +2 -1
@@ -128,7 +128,8 @@ static noinstr bool __do_fast_syscall_32 regs->ax = -EFAULT ;instrumentation_end (); -syscall_exit_to_user_mode (regs); +local_irq_disable (); +irqentry_exit_to_user_mode (regs);return false; }
[email protected]
maintainerPATCH 292/306 KVM: x86: Ensure deadline timer has truly expired before posting its IRQ
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Sean Christopherson <[email protected]>
commit beda430177f56656e7980dcce93456ffaa35676b upstream.
When posting a deadline timer interrupt, open code the checks guarding __kvm_wait_lapic_expire() in order to skip the lapic_timer_int_injected() check in kvm_wait_lapic_expire(). The injection check will always fail since the interrupt has not yet be injected. Moving the call after injection would also be wrong as that wouldn't actually delay delivery of the IRQ if it is indeed sent via posted interrupt.
Message-Id: <[email protected]>
--- arch/x86/kvm/lapic.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
arch/x86/kvm/lapic.c +10 -1
@@ -1641,7 +1641,16 @@ static void apic_timer_expired(struct kv }if (kvm_use_posted_timer_interrupt (apic->vcpu)) { -kvm_wait_lapic_expire (vcpu); +/* +* Ensure the guest's timer has truly expired before posting an +* interrupt. Open code the relevant checks to avoid querying +* lapic_timer_int_injected(), which will be false since the +* interrupt isn't yet injected. Waiting until after injecting +* is not an option since that won't help a posted interrupt. +*/ +if (vcpu->arch.apic->lapic_timer.expired_tscdeadline && + vcpu->arch.apic->lapic_timer.timer_advance_ns) +__kvm_wait_lapic_expire (vcpu);kvm_apic_inject_pending_timer_irqs (apic);return ; }
[email protected]
maintainerPATCH 293/306 KVM: kvmclock: Fix vCPUs > 64 cant be online/hotpluged
From: Greg Kroah-Hartman <[email protected]>
From: Wanpeng Li <[email protected]>
commit d7eb79c6290c7ae4561418544072e0a3266e7384 upstream.
# lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian CPU(s): 88 On-line CPU(s) list: 0-63 Off-line CPU(s) list: 64-87
# cat /proc/cmdline BOOT_IMAGE=/vmlinuz-5.10.0-rc3-tlinux2-0050+ root=/dev/mapper/cl-root ro rd.lvm.lv=cl/root rhgb quiet console=ttyS0 LANG=en_US .UTF-8 no-kvmclock-vsyscall
# echo 1 > /sys/devices/system/cpu/cpu76/online -bash: echo: write error: Cannot allocate memory
The per-cpu vsyscall pvclock data pointer assigns either an element of the static array hv_clock_boot (#vCPU <= 64) or dynamically allocated memory hvclock_mem (vCPU > 64), the dynamically memory will not be allocated if kvmclock vsyscall is disabled, this can result in cpu hotpluged fails in kvmclock_setup_percpu() which returns -ENOMEM. It's broken for no-vsyscall and sometimes you end up with vsyscall disabled if the host does something strange. This patch fixes it by allocating this dynamically memory unconditionally even if vsyscall is disabled.
Message-Id: <[email protected]>
--- arch/x86/kernel/kvmclock.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-)
arch/x86/kernel/kvmclock.c +9 -10
@@ -268,21 +268,20 @@ static void __init kvmclock_init_mem(voistatic int __init kvm_setup_vsyscall_timeinfo (void ) { -#ifdef CONFIG_X86_64 -u8 flags; +kvmclock_init_mem (); -if (!per_cpu (hv_clock_per_cpu,0 ) || !kvmclock_vsyscall) -return 0 ; +#ifdef CONFIG_X86_64 +if (per_cpu (hv_clock_per_cpu,0 ) && kvmclock_vsyscall) { +u8 flags; - flags =pvclock_read_flags (&hv_clock_boot[0 ].pvti); -if (!(flags &PVCLOCK_TSC_STABLE_BIT )) -return 0 ; + flags =pvclock_read_flags (&hv_clock_boot[0 ].pvti); +if (!(flags &PVCLOCK_TSC_STABLE_BIT )) +return 0 ; - kvm_clock.vdso_clock_mode =VDSO_CLOCKMODE_PVCLOCK ; + kvm_clock.vdso_clock_mode =VDSO_CLOCKMODE_PVCLOCK ; + }#endif -kvmclock_init_mem (); -return 0 ; }early_initcall (kvm_setup_vsyscall_timeinfo);
[email protected]
maintainerPATCH 294/306 KVM: arm64: Ensure I-cache isolation between vcpus of a same VM
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Marc Zyngier <[email protected]>
commit 01dc9262ff5797b675c32c0c6bc682777d23de05 upstream.
It recently became apparent that the ARMv8 architecture has interesting rules regarding attributes being used when fetching instructions if the MMU is off at Stage-1.
In this situation, the CPU is allowed to fetch from the PoC and allocate into the I-cache (unless the memory is mapped with the XN attribute at Stage-2).
If we transpose this to vcpus sharing a single physical CPU, it is possible for a vcpu running with its MMU off to influence another vcpu running with its MMU on, as the latter is expected to fetch from the PoU (and self-patching code doesn't flush below that level).
In order to solve this, reuse the vcpu-private TLB invalidation code to apply the same policy to the I-cache, nuking it every time the vcpu runs on a physical CPU that ran another vcpu of the same VM in the past.
This involve renaming __kvm_tlb_flush_local_vmid() to __kvm_flush_cpu_context(), and inserting a local i-cache invalidation there.
--- arch/arm64/include/asm/kvm_asm.h | 4 ++-- arch/arm64/kvm/arm.c | 7 ++++++- arch/arm64/kvm/hyp/nvhe/hyp-main.c | 6 +++--- arch/arm64/kvm/hyp/nvhe/tlb.c | 3 ++- arch/arm64/kvm/hyp/vhe/tlb.c | 3 ++- 5 files changed, 15 insertions(+), 8 deletions(-)
arch/arm64/include/asm/kvm_asm.h +2 -2
@@ -47,7 +47,7 @@#define __KVM_HOST_SMCCC_FUNC___kvm_flush_vm_context 2#define __KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid_ipa 3#define __KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid 4 -#define __KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_local_vmid 5 +#define __KVM_HOST_SMCCC_FUNC___kvm_flush_cpu_context 5#define __KVM_HOST_SMCCC_FUNC___kvm_timer_set_cntvoff 6#define __KVM_HOST_SMCCC_FUNC___kvm_enable_ssbs 7#define __KVM_HOST_SMCCC_FUNC___vgic_v3_get_ich_vtr_el2 8
@@ -183,10 +183,10 @@ DECLARE_KVM_HYP_SYM(__bp_harden_hyp_vecs#define __bp_harden_hyp_vecs CHOOSE_HYP_SYM(__bp_harden_hyp_vecs)extern void __kvm_flush_vm_context (void ); +extern void __kvm_flush_cpu_context (struct kvm_s2_mmu *mmu);extern void __kvm_tlb_flush_vmid_ipa (struct kvm_s2_mmu *mmu,phys_addr_t ipa,int level);extern void __kvm_tlb_flush_vmid (struct kvm_s2_mmu *mmu); -extern void __kvm_tlb_flush_local_vmid (struct kvm_s2_mmu *mmu);extern void __kvm_timer_set_cntvoff (u64 cntvoff);
arch/arm64/kvm/arm.c +6 -1
@@ -385,11 +385,16 @@ void kvm_arch_vcpu_load(struct kvm_vcpu last_ran =this_cpu_ptr (mmu->last_vcpu_ran);/* +* We guarantee that both TLBs and I-cache are private to each +* vcpu. If detecting that a vcpu from the same VM has +* previously run on the same physical CPU, call into the +* hypervisor code to nuke the relevant contexts. +* * We might get preempted before the vCPU actually runs, but * over-invalidation doesn't affect correctness. */ if (*last_ran != vcpu->vcpu_id) { -kvm_call_hyp (__kvm_tlb_flush_local_vmid, mmu); +kvm_call_hyp (__kvm_flush_cpu_context, mmu); *last_ran = vcpu->vcpu_id; }
arch/arm64/kvm/hyp/nvhe/hyp-main.c +3 -3
@@ -46,11 +46,11 @@ static void handle___kvm_tlb_flush_vmid(__kvm_tlb_flush_vmid (kern_hyp_va (mmu)); } -static void handle___kvm_tlb_flush_local_vmid (struct kvm_cpu_context *host_ctxt) +static void handle___kvm_flush_cpu_context (struct kvm_cpu_context *host_ctxt) { DECLARE_REG(struct kvm_s2_mmu *, mmu, host_ctxt, 1); -__kvm_tlb_flush_local_vmid (kern_hyp_va (mmu)); +__kvm_flush_cpu_context (kern_hyp_va (mmu)); }static void handle___kvm_timer_set_cntvoff (struct kvm_cpu_context *host_ctxt)
@@ -115,7 +115,7 @@ static const hcall_t *host_hcall[] = {HANDLE_FUNC (__kvm_flush_vm_context),HANDLE_FUNC (__kvm_tlb_flush_vmid_ipa),HANDLE_FUNC (__kvm_tlb_flush_vmid), -HANDLE_FUNC (__kvm_tlb_flush_local_vmid), +HANDLE_FUNC (__kvm_flush_cpu_context),HANDLE_FUNC (__kvm_timer_set_cntvoff),HANDLE_FUNC (__kvm_enable_ssbs), HANDLE_FUNC(__vgic_v3_get_ich_vtr_el2),
arch/arm64/kvm/hyp/nvhe/tlb.c +2 -1
@@ -123,7 +123,7 @@ void __kvm_tlb_flush_vmid(struct kvm_s2___tlb_switch_to_host (&cxt); } -void __kvm_tlb_flush_local_vmid (struct kvm_s2_mmu *mmu) +void __kvm_flush_cpu_context (struct kvm_s2_mmu *mmu) {struct tlb_inv_context cxt;
@@ -131,6 +131,7 @@ void __kvm_tlb_flush_local_vmid(struct k__tlb_switch_to_guest (mmu, &cxt);__tlbi (vmalle1); + asmvolatile ("ic iallu" );dsb (nsh);isb ();
arch/arm64/kvm/hyp/vhe/tlb.c +2 -1
@@ -127,7 +127,7 @@ void __kvm_tlb_flush_vmid(struct kvm_s2___tlb_switch_to_host (&cxt); } -void __kvm_tlb_flush_local_vmid (struct kvm_s2_mmu *mmu) +void __kvm_flush_cpu_context (struct kvm_s2_mmu *mmu) {struct tlb_inv_context cxt;
@@ -135,6 +135,7 @@ void __kvm_tlb_flush_local_vmid(struct k__tlb_switch_to_guest (mmu, &cxt);__tlbi (vmalle1); + asmvolatile ("ic iallu" );dsb (nsh);isb ();
[email protected]
maintainerPATCH 295/306 KVM: arm64: Fix range alignment when walking page tables
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Jia He <[email protected]>
commit 357ad203d45c0f9d76a8feadbd5a1c5d460c638b upstream.
When walking the page tables at a given level, and if the start address for the range isn't aligned for that level, we propagate the misalignment on each iteration at that level.
This results in the walker ignoring a number of entries (depending on the original misalignment) on each subsequent iteration.
Properly aligning the address before the next iteration addresses this issue.
Message-Id: <[email protected]>
--- arch/arm64/kvm/hyp/pgtable.c | 1 + 1 file changed, 1 insertion(+)
arch/arm64/kvm/hyp/pgtable.c +1 -0
@@ -225,6 +225,7 @@ static inline int __kvm_pgtable_visit(st goto out;if (!table) { + data->addr =ALIGN_DOWN (data->addr,kvm_granule_size (level)); data->addr +=kvm_granule_size (level); goto out; }
[email protected]
maintainerPATCH 296/306 KVM: arm64: Avoid corrupting vCPU context register in guest exit
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Will Deacon <[email protected]>
commit 31948332d5fa392ad933f4a6a10026850649ed76 upstream.
Commit 7db21530479f ("KVM: arm64: Restore hyp when panicking in guest context") tracks the currently running vCPU, clearing the pointer to NULL on exit from a guest.
Unfortunately, the use of 'set_loaded_vcpu' clobbers x1 to point at the kvm_hyp_ctxt instead of the vCPU context, causing the subsequent RAS code to go off into the weeds when it saves the DISR assuming that the CPU context is embedded in a struct vCPU.
Leave x1 alone and use x3 as a temporary register instead when clearing the vCPU on the guest exit path.
Message-Id: <[email protected]>
--- arch/arm64/kvm/hyp/entry.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/kvm/hyp/entry.S +1 -1
@@ -146,7 +146,7 @@ SYM_INNER_LABEL(__guest_exit, SYM_L_GLOB // Now restore the hyp regs restore_callee_saved_regs x2 - set_loaded_vcpu xzr, x1, x2 + set_loaded_vcpu xzr, x2, x3 alternative_if ARM64_HAS_RAS_EXTN // If we have the RAS extensions we can consume a pending error
[email protected]
maintainerPATCH 297/306 KVM: arm64: nvhe: Save the SPE context early
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Suzuki K Poulose <[email protected]>
commit b96b0c5de685df82019e16826a282d53d86d112c upstream.
The nVHE KVM hyp drains and disables the SPE buffer, before entering the guest, as the EL1&0 translation regime is going to be loaded with that of the guest.
But this operation is performed way too late, because :
- The owning translation regime of the SPE buffer
is transferred to EL2. (MDCR_EL2_E2PB == 0)
- The guest Stage1 is loaded.
Thus the flush could use the host EL1 virtual address, but use the EL2 translations instead of host EL1, for writing out any cached data.
Fix this by moving the SPE buffer handling early enough. The restore path is doing the right thing.
Message-Id: <[email protected]>
--- arch/arm64/include/asm/kvm_hyp.h | 5 +++++ arch/arm64/kvm/hyp/nvhe/debug-sr.c | 12 ++++++++++-- arch/arm64/kvm/hyp/nvhe/switch.c | 11 ++++++++++- 3 files changed, 25 insertions(+), 3 deletions(-)
arch/arm64/include/asm/kvm_hyp.h +5 -0
@@ -83,6 +83,11 @@ void sysreg_restore_guest_state_vhe(struvoid __debug_switch_to_guest (struct kvm_vcpu *vcpu);void __debug_switch_to_host (struct kvm_vcpu *vcpu); +#ifdef __KVM_NVHE_HYPERVISOR__ +void __debug_save_host_buffers_nvhe (struct kvm_vcpu *vcpu); +void __debug_restore_host_buffers_nvhe (struct kvm_vcpu *vcpu); +#endif +void __fpsimd_save_state (struct user_fpsimd_state *fp_regs);void __fpsimd_restore_state (struct user_fpsimd_state *fp_regs);
arch/arm64/kvm/hyp/nvhe/debug-sr.c +10 -2
@@ -58,16 +58,24 @@ static void __debug_restore_spe(u64 pmscwrite_sysreg_s (pmscr_el1,SYS_PMSCR_EL1 ); } -void __debug_switch_to_guest (struct kvm_vcpu *vcpu) +void __debug_save_host_buffers_nvhe (struct kvm_vcpu *vcpu) {/* Disable and flush SPE data generation */ __debug_save_spe (&vcpu->arch.host_debug_state.pmscr_el1); +} + +void __debug_switch_to_guest (struct kvm_vcpu *vcpu) +{__debug_switch_to_guest_common (vcpu); } -void __debug_switch_to_host (struct kvm_vcpu *vcpu) +void __debug_restore_host_buffers_nvhe (struct kvm_vcpu *vcpu) {__debug_restore_spe (vcpu->arch.host_debug_state.pmscr_el1); +} + +void __debug_switch_to_host (struct kvm_vcpu *vcpu) +{__debug_switch_to_host_common (vcpu); }
arch/arm64/kvm/hyp/nvhe/switch.c +10 -1
@@ -192,6 +192,14 @@ int __kvm_vcpu_run(struct kvm_vcpu *vcpu pmu_switch_needed =__pmu_switch_to_guest (host_ctxt);__sysreg_save_state_nvhe (host_ctxt); +/* +* We must flush and disable the SPE buffer for nVHE, as +* the translation regime(EL1&0) is going to be loaded with +* that of the guest. And we must do this before we change the +* translation regime to EL2 (via MDCR_EL2_E2PB == 0) and +* before we load guest Stage1. +*/ +__debug_save_host_buffers_nvhe (vcpu);__adjust_pc (vcpu);
@@ -234,11 +242,12 @@ int __kvm_vcpu_run(struct kvm_vcpu *vcpuif (vcpu->arch.flags &KVM_ARM64_FP_ENABLED )__fpsimd_save_fpexc32 (vcpu); +__debug_switch_to_host (vcpu);/* * This must come after restoring the host sysregs, since a non-VHE * system may enable SPE here and make use of the TTBRs. */ -__debug_switch_to_host (vcpu); +__debug_restore_host_buffers_nvhe (vcpu);if (pmu_switch_needed)__pmu_switch_to_host (host_ctxt);
[email protected]
maintainerPATCH 298/306 KVM: arm64: Reject VM creation when the default IPA size is unsupported
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Marc Zyngier <[email protected]>
commit 7d717558dd5ef10d28866750d5c24ff892ea3778 upstream.
KVM/arm64 has forever used a 40bit default IPA space, partially due to its 32bit heritage (where the only choice is 40bit).
However, there are implementations in the wild that have a *cough* much smaller *cough* IPA space, which leads to a misprogramming of VTCR_EL2, and a guest that is stuck on its first memory access if userspace dares to ask for the default IPA setting (which most VMMs do).
Instead, blundly reject the creation of such VM, as we can't satisfy the requirements from userspace (with a one-off warning). Also clarify the boot warning, and document that the VM creation will fail when an unsupported IPA size is provided.
Although this is an ABI change, it doesn't really change much for userspace:
- the guest couldn't run before this change, but no error was returned. At least userspace knows what is happening.
- a memory slot that was accepted because it did fit the default IPA space now doesn't even get a chance to be registered.
The other thing that is left doing is to convince userspace to actually use the IPA space setting instead of relying on the antiquated default.
--- Documentation/virt/kvm/api.rst | 3 +++ arch/arm64/kvm/reset.c | 12 ++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-)
Documentation/virt/kvm/api.rst +3 -0
@@ -182,6 +182,9 @@ is dependent on the CPU capability and t be retrieved using KVM_CAP_ARM_VM_IPA_SIZE of the KVM_CHECK_EXTENSION ioctl() at run-time. +Creation of the VM will fail if the requested IPA size (whether it is +implicit or explicit) is unsupported on the host. + Please note that configuring the IPA size does not affect the capability exposed by the guest CPUs in ID_AA64MMFR0_EL1[PARange]. It only affects size of the address translated by the stage2 level (guest physical to
arch/arm64/kvm/reset.c +8 -4
@@ -324,10 +324,9 @@ int kvm_set_ipa_limit(void) } kvm_ipa_limit =id_aa64mmfr0_parange_to_phys_shift (parange); -WARN (kvm_ipa_limit <KVM_PHYS_SHIFT , -"KVM IPA Size Limit (%d bits) is smaller than default size\n" , - kvm_ipa_limit); -kvm_info ("IPA Size Limit: %d bits\n" , kvm_ipa_limit); +kvm_info ("IPA Size Limit: %d bits%s\n" , kvm_ipa_limit, + ((kvm_ipa_limit <KVM_PHYS_SHIFT ) ? +" (Reduced IPA size, limited VM/VMM compatibility)" :"" ));return 0 ; }
@@ -356,6 +355,11 @@ int kvm_arm_setup_stage2(struct kvm *kvmreturn -EINVAL ; }else { phys_shift =KVM_PHYS_SHIFT ; +if (phys_shift > kvm_ipa_limit) { +pr_warn_once ("%s using unsupported default IPA limit, upgrade your VMM\n" , + current->comm); +return -EINVAL ; + } } mmfr0 =read_sanitised_ftr_reg (SYS_ID_AA64MMFR0_EL1 );
[email protected]
maintainerPATCH 299/306 KVM: arm64: Fix exclusive limit for IPA size
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Marc Zyngier <[email protected]>
commit 262b003d059c6671601a19057e9fe1a5e7f23722 upstream.
When registering a memslot, we check the size and location of that memslot against the IPA size to ensure that we can provide guest access to the whole of the memory.
Unfortunately, this check rejects memslot that end-up at the exact limit of the addressing capability for a given IPA size. For example, it refuses the creation of a 2GB memslot at 0x8000000 with a 32bit IPA space.
Fix it by relaxing the check to accept a memslot reaching the limit of the IPA space.
--- arch/arm64/kvm/mmu.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
arch/arm64/kvm/mmu.c +1 -2
@@ -1309,8 +1309,7 @@ int kvm_arch_prepare_memory_region(struc* Prevent userspace from creating a memory region outside of the IPA * space addressable by the KVM guest IPA space. */ -if (memslot->base_gfn + memslot->npages >= - (kvm_phys_size (kvm) >>PAGE_SHIFT )) +if ((memslot->base_gfn + memslot->npages) > (kvm_phys_size (kvm) >>PAGE_SHIFT ))return -EFAULT ;mmap_read_lock (current->mm);
[email protected]
maintainerPATCH 300/306 mm/highmem.c: fix zero_user_segments() with start > end
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: OGAWA Hirofumi <[email protected]>
commit 184cee516f3e24019a08ac8eb5c7cf04c00933cb upstream.
zero_user_segments() is used from __block_write_begin_int(), for example like the following
zero_user_segments(page, 4096, 1024, 512, 918)
But new the zero_user_segments() implementation for for HIGHMEM + TRANSPARENT_HUGEPAGE doesn't handle "start > end" case correctly, and hits BUG_ON(). (we can fix __block_write_begin_int() instead though, it is the old and multiple usage)
Also it calls kmap_atomic() unnecessarily while start == end == 0.
--- mm/highmem.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
mm/highmem.c +12 -5
@@ -368,20 +368,24 @@ void zero_user_segments(struct page *pagBUG_ON (end1 >page_size (page) || end2 >page_size (page)); +if (start1 >= end1) + start1 = end1 =0 ; +if (start2 >= end2) + start2 = end2 =0 ; +for (i =0 ; i <compound_nr (page); i++) {void *kaddr =NULL ; -if (start1 <PAGE_SIZE || start2 <PAGE_SIZE ) - kaddr =kmap_atomic (page + i); -if (start1 >=PAGE_SIZE ) { start1 -=PAGE_SIZE ; end1 -=PAGE_SIZE ; }else {unsigned this_end =min_t (unsigned, end1,PAGE_SIZE ); -if (end1 > start1) +if (end1 > start1) { + kaddr =kmap_atomic (page + i);memset (kaddr + start1,0 , this_end - start1); + } end1 -= this_end; start1 =0 ; }
@@ -392,8 +396,11 @@ void zero_user_segments(struct page *pag }else {unsigned this_end =min_t (unsigned, end2,PAGE_SIZE ); -if (end2 > start2) +if (end2 > start2) { +if (!kaddr) + kaddr =kmap_atomic (page + i);memset (kaddr + start2,0 , this_end - start2); + } end2 -= this_end; start2 =0 ; }
[email protected]
maintainerPATCH 301/306 mm/userfaultfd: fix memory corruption due to writeprotect
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Nadav Amit <[email protected]>
commit 6ce64428d62026a10cb5d80138ff2f90cc21d367 upstream.
Userfaultfd self-test fails occasionally, indicating a memory corruption.
Analyzing this problem indicates that there is a real bug since mmap_lock is only taken for read in mwriteprotect_range() and defers flushes, and since there is insufficient consideration of concurrent deferred TLB flushes in wp_page_copy(). Although the PTE is flushed from the TLBs in wp_page_copy(), this flush takes place after the copy has already been performed, and therefore changes of the page are possible between the time of the copy and the time in which the PTE is flushed.
To make matters worse, memory-unprotection using userfaultfd also poses a problem. Although memory unprotection is logically a promotion of PTE permissions, and therefore should not require a TLB flush, the current userrfaultfd code might actually cause a demotion of the architectural PTE
permission: when userfaultfd_writeprotect() unprotects memory region, it unintentionally *clears* the RW-bit if it was already set. Note that this unprotecting a PTE that is not write-protected is a valid use-case: the userfaultfd monitor might ask to unprotect a region that holds both write-protected and write-unprotected PTEs.
The scenario that happens in selftests/vm/userfaultfd is as follows:
cpu0 cpu1 cpu2
---- ---- ----
[ Writable PTE
cached in TLB ]userfaultfd_writeprotect()
[ write-*unprotect* ]mwriteprotect_range()mmap_read_lock()change_protection()
change_protection_range()
...change_pte_range()
[ *clear* “write”-bit ]
[ defer TLB flushes ]
[ page-fault ] ... wp_page_copy() cow_user_page() [ copy page ] [ write to old page ] ... set_pte_at_notify()
A similar scenario can happen:
cpu0 cpu1 cpu2 cpu3
---- ---- ---- ----
[ Writable PTE
cached in TLB ]userfaultfd_writeprotect()
[ write-protect ]
[ deferred TLB flush ]
userfaultfd_writeprotect() [ write-unprotect ] [ deferred TLB flush] [ page-fault ] wp_page_copy() cow_user_page() [ copy page ] ... [ write to page ] set_pte_at_notify()
This race exists since commit 292924b26024 ("userfaultfd: wp: apply _PAGE_UFFD_WP bit"). Yet, as Yu Zhao pointed, these races became apparent since commit 09854ba94c6a ("mm: do_wp_page() simplification") which made wp_page_copy() more likely to take place, specifically if page_count(page)
Quoted 1 line
1.
To resolve the aforementioned races, check whether there are pending flushes on uffd-write-protected VMAs, and if there are, perform a flush before doing the COW.
Further optimizations will follow to avoid during uffd-write-unprotect unnecassary PTE write-protection and TLB flushes.
--- mm/memory.c | 8 ++++++++ 1 file changed, 8 insertions(+)
mm/memory.c +8 -0
@@ -3092,6 +3092,14 @@ static vm_fault_t do_wp_page(struct vm_freturn handle_userfault (vmf,VM_UFFD_WP ); } +/* +* Userfaultfd write-protect can defer flushes. Ensure the TLB +* is flushed in this case before copying. +*/ +if (unlikely (userfaultfd_wp (vmf->vma) && +mm_tlb_flush_pending (vmf->vma->vm_mm))) +flush_tlb_page (vmf->vma, vmf->address); + vmf->page =vm_normal_page (vma, vmf->address, vmf->orig_pte);if (!vmf->page) {/*
[email protected]
maintainerPATCH 302/306 mm/madvise: replace ptrace attach requirement for process_madvise
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Suren Baghdasaryan <[email protected]>
commit 96cfe2c0fd23ea7c2368d14f769d287e7ae1082e upstream.
process_madvise currently requires ptrace attach capability. PTRACE_MODE_ATTACH gives one process complete control over another process. It effectively removes the security boundary between the two processes (in one direction). Granting ptrace attach capability even to a system process is considered dangerous since it creates an attack surface. This severely limits the usage of this API.
The operations process_madvise can perform do not affect the correctness of the operation of the target process; they only affect where the data is physically located (and therefore, how fast it can be accessed). What we want is the ability for one process to influence another process in order to optimize performance across the entire system while leaving the security boundary intact.
Replace PTRACE_MODE_ATTACH with a combination of PTRACE_MODE_READ and CAP_SYS_NICE. PTRACE_MODE_READ to prevent leaking ASLR metadata and CAP_SYS_NICE for influencing process performance.
--- mm/madvise.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
mm/madvise.c +12 -1
@@ -1197,12 +1197,22 @@ SYSCALL_DEFINE5(process_madvise, int, pi goto release_task; } - mm =mm_access (task,PTRACE_MODE_ATTACH_FSCREDS ); +/* Require PTRACE_MODE_READ to avoid leaking ASLR metadata. */ + mm =mm_access (task,PTRACE_MODE_READ_FSCREDS );if (IS_ERR_OR_NULL (mm)) { ret =IS_ERR (mm) ?PTR_ERR (mm) : -ESRCH ; goto release_task; } +/* +* Require CAP_SYS_NICE for influencing process performance. Note that +* only non-destructive hints are currently supported. +*/ +if (!capable (CAP_SYS_NICE )) { + ret = -EPERM ; + goto release_mm; + } + total_len =iov_iter_count (&iter);while (iov_iter_count (&iter)) {
@@ -1217,6 +1227,7 @@ SYSCALL_DEFINE5(process_madvise, int, piif (ret ==0 ) ret = total_len -iov_iter_count (&iter); +release_mm:mmput (mm); release_task:put_task_struct (task);
[email protected]
maintainerPATCH 303/306 mm/memcg: set memcg when splitting page
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Zhou Guanghui <[email protected]>
commit e1baddf8475b06cc56f4bafecf9a32a124343d9f upstream.
As described in the split_page() comment, for the non-compound high order page, the sub-pages must be freed individually. If the memcg of the first page is valid, the tail pages cannot be uncharged when be freed.
For example, when alloc_pages_exact is used to allocate 1MB continuous physical memory, 2MB is charged(kmemcg is enabled and __GFP_ACCOUNT is set). When make_alloc_exact free the unused 1MB and free_pages_exact free the applied 1MB, actually, only 4KB(one page) is uncharged.
Therefore, the memcg of the tail page needs to be set when splitting a page.
Michel:
There are at least two explicit users of __GFP_ACCOUNT with alloc_exact_pages added recently. See 7efe8ef274024 ("KVM: arm64:
Allocate stage-2 pgd pages with GFP_KERNEL_ACCOUNT") and c419621873713 ("KVM: s390: Add memcg accounting to KVM allocations"), so this is not just a theoretical issue.
--- mm/page_alloc.c | 1 + 1 file changed, 1 insertion(+)
mm/page_alloc.c +1 -0
@@ -3313,6 +3313,7 @@ void split_page(struct page *page, unsigfor (i =1 ; i < (1 << order); i++)set_page_refcounted (page + i);split_page_owner (page,1 << order); +split_page_memcg (page,1 << order); }EXPORT_SYMBOL_GPL (split_page);
[email protected]
maintainerPATCH 304/306 mm/memcg: rename mem_cgroup_split_huge_fixup to split_page_memcg and add nr_pages argument
In reply to [email protected]From: Greg Kroah-Hartman <[email protected]>
From: Zhou Guanghui <[email protected]>
commit be6c8982e4ab9a41907555f601b711a7e2a17d4c upstream.
Rename mem_cgroup_split_huge_fixup to split_page_memcg and explicitly pass in page number argument.
In this way, the interface name is more common and can be used by potential users. In addition, the complete info(memcg and flag) of the memcg needs to be set to the tail pages.
--- include/linux/memcontrol.h | 6 ++---- mm/huge_memory.c | 2 +- mm/memcontrol.c | 15 ++++++--------- 3 files changed, 9 insertions(+), 14 deletions(-)
include/linux/memcontrol.h +2 -4
@@ -1072,9 +1072,7 @@ static inline void memcg_memory_event_mm rcu_read_unlock(); } -#ifdef CONFIG_TRANSPARENT_HUGEPAGE -void mem_cgroup_split_huge_fixup (struct page *head); -#endif +void split_page_memcg (struct page *head,unsigned int nr);#else /* CONFIG_MEMCG */
@@ -1416,7 +1414,7 @@ unsigned long mem_cgroup_soft_limit_reclreturn 0 ; } -static inline void mem_cgroup_split_huge_fixup (struct page *head) +static inline void split_page_memcg (struct page *head,unsigned int nr) { }
mm/huge_memory.c +1 -1
@@ -2465,7 +2465,7 @@ static void __split_huge_page(struct pagint i;/* complete memcg works before add pages to LRU */ -mem_cgroup_split_huge_fixup (head); +split_page_memcg (head, nr);if (PageAnon (head) &&PageSwapCache (head)) {swp_entry_t entry = { .val =page_private (head) };
mm/memcontrol.c +6 -9
@@ -3296,24 +3296,21 @@ void obj_cgroup_uncharge(struct obj_cgro#endif /* CONFIG_MEMCG_KMEM */ -#ifdef CONFIG_TRANSPARENT_HUGEPAGE /* -* Because page_memcg(head) is not set on compound tails, set it now. +* Because page_memcg(head) is not set on tails, set it now. */ -void mem_cgroup_split_huge_fixup (struct page *head) +void split_page_memcg (struct page *head,unsigned int nr) {struct mem_cgroup *memcg =page_memcg (head);int i; -if (mem_cgroup_disabled ()) +if (mem_cgroup_disabled () || !memcg)return ; -for (i =1 ; i <HPAGE_PMD_NR ; i++) { -css_get (&memcg->css); - head[i].memcg_data = (unsigned long )memcg; - } +for (i =1 ; i < nr; i++) + head[i].memcg_data = head->memcg_data; +css_get_many (&memcg->css, nr -1 ); } -#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ #ifdef CONFIG_MEMCG_SWAP /**