5.10.173-rc1 review
Subsystems (7)
Greg Kroah-Hartman
maintainerPATCH 285/529 wifi: brcmfmac: Fix potential stack-out-of-bounds in brcmf_c_preinit_dcmds()
In reply to Greg Kroah-HartmanFrom: Jisoo Jang <[email protected]>
[ Upstream commit 0a06cadcc2a0044e4a117cc0e61436fc3a0dad69 ]
This patch fixes a stack-out-of-bounds read in brcmfmac that occurs when 'buf' that is not null-terminated is passed as an argument of strsep() in brcmf_c_preinit_dcmds(). This buffer is filled with a firmware version string by memcpy() in brcmf_fil_iovar_data_get().
The patch ensures buf is null-terminated.
Found by a modified version of syzkaller.
[ 47.569679][ T1897] brcmfmac: brcmf_fw_alloc_request: using brcm/brcmfmac43236b for chip BCM43236/3 [ 47.582839][ T1897] brcmfmac: brcmf_c_process_clm_blob: no clm_blob available (err=-2), device may have limited channels available [ 47.601565][ T1897] ================================================================== [ 47.602574][ T1897] BUG: KASAN: stack-out-of-bounds in strsep+0x1b2/0x1f0 [ 47.603447][ T1897] Read of size 1 at addr ffffc90001f6f000 by task kworker/0:2/1897 [ 47.604336][ T1897] [ 47.604621][ T1897] CPU: 0 PID: 1897 Comm: kworker/0:2 Tainted: G O 5.14.0+ #131 [ 47.605617][ T1897] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014 [ 47.606907][ T1897] Workqueue: usb_hub_wq hub_event [ 47.607453][ T1897] Call Trace: [ 47.607801][ T1897] dump_stack_lvl+0x8e/0xd1 [ 47.608295][ T1897] print_address_description.constprop.0.cold+0xf/0x334 [ 47.609009][ T1897] ? strsep+0x1b2/0x1f0 [ 47.609434][ T1897] ? strsep+0x1b2/0x1f0 [ 47.609863][ T1897] kasan_report.cold+0x83/0xdf [ 47.610366][ T1897] ? strsep+0x1b2/0x1f0 [ 47.610882][ T1897] strsep+0x1b2/0x1f0 [ 47.611300][ T1897] ? brcmf_fil_iovar_data_get+0x3a/0xf0 [ 47.611883][ T1897] brcmf_c_preinit_dcmds+0x995/0xc40 [ 47.612434][ T1897] ? brcmf_c_set_joinpref_default+0x100/0x100 [ 47.613078][ T1897] ? rcu_read_lock_sched_held+0xa1/0xd0 [ 47.613662][ T1897] ? rcu_read_lock_bh_held+0xb0/0xb0 [ 47.614208][ T1897] ? lock_acquire+0x19d/0x4e0 [ 47.614704][ T1897] ? find_held_lock+0x2d/0x110 [ 47.615236][ T1897] ? brcmf_usb_deq+0x1a7/0x260 [ 47.615741][ T1897] ? brcmf_usb_rx_fill_all+0x5a/0xf0 [ 47.616288][ T1897] brcmf_attach+0x246/0xd40 [ 47.616758][ T1897] ? wiphy_new_nm+0x1703/0x1dd0 [ 47.617280][ T1897] ? kmemdup+0x43/0x50 [ 47.617720][ T1897] brcmf_usb_probe+0x12de/0x1690 [ 47.618244][ T1897] ? brcmf_usbdev_qinit.constprop.0+0x470/0x470 [ 47.618901][ T1897] usb_probe_interface+0x2aa/0x760 [ 47.619429][ T1897] ? usb_probe_device+0x250/0x250 [ 47.619950][ T1897] really_probe+0x205/0xb70 [ 47.620435][ T1897] ? driver_allows_async_probing+0x130/0x130 [ 47.621048][ T1897] __driver_probe_device+0x311/0x4b0 [ 47.621595][ T1897] ? driver_allows_async_probing+0x130/0x130 [ 47.622209][ T1897] driver_probe_device+0x4e/0x150 [ 47.622739][ T1897] __device_attach_driver+0x1cc/0x2a0 [ 47.623287][ T1897] bus_for_each_drv+0x156/0x1d0 [ 47.623796][ T1897] ? bus_rescan_devices+0x30/0x30 [ 47.624309][ T1897] ? lockdep_hardirqs_on_prepare+0x273/0x3e0 [ 47.624907][ T1897] ? trace_hardirqs_on+0x46/0x160 [ 47.625437][ T1897] __device_attach+0x23f/0x3a0 [ 47.625924][ T1897] ? device_bind_driver+0xd0/0xd0 [ 47.626433][ T1897] ? kobject_uevent_env+0x287/0x14b0 [ 47.627057][ T1897] bus_probe_device+0x1da/0x290 [ 47.627557][ T1897] device_add+0xb7b/0x1eb0 [ 47.628027][ T1897] ? wait_for_completion+0x290/0x290 [ 47.628593][ T1897] ? __fw_devlink_link_to_suppliers+0x5a0/0x5a0 [ 47.629249][ T1897] usb_set_configuration+0xf59/0x16f0 [ 47.629829][ T1897] usb_generic_driver_probe+0x82/0xa0 [ 47.630385][ T1897] usb_probe_device+0xbb/0x250 [ 47.630927][ T1897] ? usb_suspend+0x590/0x590 [ 47.631397][ T1897] really_probe+0x205/0xb70 [ 47.631855][ T1897] ? driver_allows_async_probing+0x130/0x130 [ 47.632469][ T1897] __driver_probe_device+0x311/0x4b0 [ 47.633002][ T1897] ? usb_generic_driver_match+0x75/0x90 [ 47.633573][ T1897] ? driver_allows_async_probing+0x130/0x130 [ 47.634170][ T1897] driver_probe_device+0x4e/0x150 [ 47.634703][ T1897] __device_attach_driver+0x1cc/0x2a0 [ 47.635248][ T1897] bus_for_each_drv+0x156/0x1d0 [ 47.635748][ T1897] ? bus_rescan_devices+0x30/0x30 [ 47.636271][ T1897] ? lockdep_hardirqs_on_prepare+0x273/0x3e0 [ 47.636881][ T1897] ? trace_hardirqs_on+0x46/0x160 [ 47.637396][ T1897] __device_attach+0x23f/0x3a0 [ 47.637904][ T1897] ? device_bind_driver+0xd0/0xd0 [ 47.638426][ T1897] ? kobject_uevent_env+0x287/0x14b0 [ 47.638985][ T1897] bus_probe_device+0x1da/0x290 [ 47.639512][ T1897] device_add+0xb7b/0x1eb0 [ 47.639977][ T1897] ? __fw_devlink_link_to_suppliers+0x5a0/0x5a0 [ 47.640612][ T1897] ? kfree+0x14a/0x6b0 [ 47.641055][ T1897] ? __usb_get_extra_descriptor+0x116/0x160 [ 47.641679][ T1897] usb_new_device.cold+0x49c/0x1029 [ 47.642245][ T1897] ? hub_disconnect+0x450/0x450 [ 47.642756][ T1897] ? rwlock_bug.part.0+0x90/0x90 [ 47.643273][ T1897] ? _raw_spin_unlock_irq+0x24/0x30 [ 47.643822][ T1897] ? lockdep_hardirqs_on_prepare+0x273/0x3e0 [ 47.644445][ T1897] hub_event+0x1c98/0x3950 [ 47.644939][ T1897] ? hub_port_debounce+0x2e0/0x2e0 [ 47.645467][ T1897] ? check_irq_usage+0x861/0xf20 [ 47.645975][ T1897] ? drain_workqueue+0x280/0x360 [ 47.646506][ T1897] ? lock_release+0x640/0x640 [ 47.646994][ T1897] ? rcu_read_lock_sched_held+0xa1/0xd0 [ 47.647572][ T1897] ? rcu_read_lock_bh_held+0xb0/0xb0 [ 47.648111][ T1897] ? lockdep_hardirqs_on_prepare+0x273/0x3e0 [ 47.648735][ T1897] process_one_work+0x92b/0x1460 [ 47.649262][ T1897] ? pwq_dec_nr_in_flight+0x330/0x330 [ 47.649816][ T1897] ? rwlock_bug.part.0+0x90/0x90 [ 47.650336][ T1897] worker_thread+0x95/0xe00 [ 47.650830][ T1897] ? __kthread_parkme+0x115/0x1e0 [ 47.651361][ T1897] ? process_one_work+0x1460/0x1460 [ 47.651904][ T1897] kthread+0x3a1/0x480 [ 47.652329][ T1897] ? set_kthread_struct+0x120/0x120 [ 47.652878][ T1897] ret_from_fork+0x1f/0x30 [ 47.653370][ T1897] [ 47.653608][ T1897] [ 47.653848][ T1897] addr ffffc90001f6f000 is located in stack of task kworker/0:2/1897 at offset 512 in frame: [ 47.654891][ T1897] brcmf_c_preinit_dcmds+0x0/0xc40 [ 47.655442][ T1897] [ 47.655690][ T1897] this frame has 4 objects: [ 47.656151][ T1897] [48, 56) 'ptr' [ 47.656159][ T1897] [80, 148) 'revinfo' [ 47.656534][ T1897] [192, 210) 'eventmask' [ 47.656953][ T1897] [256, 512) 'buf' [ 47.657410][ T1897] [ 47.658035][ T1897] Memory state around the buggy address: [ 47.658743][ T1897] ffffc90001f6ef00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 47.659577][ T1897] ffffc90001f6ef80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 47.660394][ T1897] >ffffc90001f6f000: f3 f3 f3 f3 f3 f3 f3 f3 00 00 00 00 00 00 00 00 [ 47.661199][ T1897] ^ [ 47.661625][ T1897] ffffc90001f6f080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 47.662455][ T1897] ffffc90001f6f100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 [ 47.663318][ T1897] ================================================================== [ 47.664147][ T1897] Disabling lock debugging due to kernel taint
--- drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +1 -0
@@ -264,6 +264,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) err); goto done; } + buf[sizeof (buf) -1 ] ='\0' ; ptr = (char *)buf;strsep (&ptr,"\n" );
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 286/529 rcu: Make RCU_LOCKDEP_WARN() avoid early lockdep checks
In reply to Greg Kroah-HartmanFrom: Paul E. McKenney <[email protected]>
[ Upstream commit 0cae5ded535c3a80aed94f119bbd4ee3ae284a65 ]
Currently, RCU_LOCKDEP_WARN() checks the condition before checking to see if lockdep is still enabled. This is necessary to avoid the false-positive splats fixed by commit 3066820034b5dd ("rcu: Reject RCU_LOCKDEP_WARN() false positives"). However, the current state can result in false-positive splats during early boot before lockdep is fully initialized. This commit therefore checks debug_lockdep_rcu_enabled() both before and after checking the condition, thus avoiding both sets of false-positive error reports.
--- include/linux/rcupdate.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
include/linux/rcupdate.h +8 -1
@@ -308,11 +308,18 @@ static inline int rcu_read_lock_any_held(void)* RCU_LOCKDEP_WARN - emit lockdep splat if specified condition is met * @c: condition to check * @s: informative message +* +* This checks debug_lockdep_rcu_enabled() before checking (c) to +* prevent early boot splats due to lockdep not yet being initialized, +* and rechecks it after checking (c) to prevent false-positive splats +* due to races with lockdep being disabled. See commit 3066820034b5dd +* ("rcu: Reject RCU_LOCKDEP_WARN() false positives") for more detail. */ #define RCU_LOCKDEP_WARN (c, s) \ do { \ static bool __section(".data.unlikely") __warned; \ - if ((c) && debug_lockdep_rcu_enabled() && !__warned) { \ + if (debug_lockdep_rcu_enabled() && (c) && \ + debug_lockdep_rcu_enabled() && !__warned) { \ __warned = true; \ lockdep_rcu_suspicious(__FILE__, __LINE__, s); \ } \
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 287/529 rcu: Suppress smp_processor_id() complaint in synchronize_rcu_expedited_wait()
In reply to Greg Kroah-HartmanFrom: Paul E. McKenney <[email protected]>
[ Upstream commit 2d7f00b2f01301d6e41fd4a28030dab0442265be ]
The normal grace period's RCU CPU stall warnings are invoked from the scheduling-clock interrupt handler, and can thus invoke smp_processor_id() with impunity, which allows them to directly invoke dump_cpu_task(). In contrast, the expedited grace period's RCU CPU stall warnings are invoked from process context, which causes the dump_cpu_task() function's calls to smp_processor_id() to complain bitterly in debug kernels.
This commit therefore causes synchronize_rcu_expedited_wait() to disable preemption around its call to dump_cpu_task().
--- kernel/rcu/tree_exp.h | 2 ++ 1 file changed, 2 insertions(+)
kernel/rcu/tree_exp.h +2 -0
@@ -564,7 +564,9 @@ static void synchronize_rcu_expedited_wait(void) mask =leaf_node_cpu_bit (rnp, cpu);if (!(READ_ONCE (rnp->expmask) & mask))continue ; +preempt_disable ();// For smp_processor_id() in dump_cpu_task(). dump_cpu_task (cpu); +preempt_enable (); } } jiffies_stall =3 *rcu_jiffies_till_stall_check () +3 ;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 288/529 rcu-tasks: Make rude RCU-Tasks work well with CPU hotplug
In reply to Greg Kroah-HartmanFrom: Zqiang <[email protected]>
[ Upstream commit ea5c8987fef20a8cca07e428aa28bc64649c5104 ]
The synchronize_rcu_tasks_rude() function invokes rcu_tasks_rude_wait_gp() to wait one rude RCU-tasks grace period. The rcu_tasks_rude_wait_gp() function in turn checks if there is only a single online CPU. If so, it will immediately return, because a call to synchronize_rcu_tasks_rude() is by definition a grace period on a single-CPU system. (We could have blocked!)
Unfortunately, this check uses num_online_cpus() without synchronization, which can result in too-short grace periods. To see this, consider the following scenario:
CPU0 CPU1 (going offline)
migration/1 task:
cpu_stopper_thread
-> take_cpu_down
-> _cpu_disable
(dec __num_online_cpus)
->cpuhp_invoke_callback
preempt_disable
access old_data0
task1
del old_data0 .....
synchronize_rcu_tasks_rude()
task1 schedule out
....
task2 schedule in
rcu_tasks_rude_wait_gp()
->__num_online_cpus == 1
->return ....
task1 schedule in
->free old_data0
preempt_enable
When CPU1 decrements __num_online_cpus, its value becomes 1. However, CPU1 has not finished going offline, and will take one last trip through the scheduler and the idle loop before it actually stops executing instructions. Because synchronize_rcu_tasks_rude() is mostly used for tracing, and because both the scheduler and the idle loop can be traced, this means that CPU0's prematurely ended grace period might disrupt the tracing on CPU1. Given that this disruption might include CPU1 executing instructions in memory that was just now freed (and maybe reallocated), this is a matter of some concern.
This commit therefore removes that problematic single-CPU check from the rcu_tasks_rude_wait_gp() function. This dispenses with the single-CPU optimization, but there is no evidence indicating that this optimization is important. In addition, synchronize_rcu_tasks_generic() contains a similar optimization (albeit only for early boot), which also splats. (As in exactly why are you invoking synchronize_rcu_tasks_rude() so early in boot, anyway???)
It is OK for the synchronize_rcu_tasks_rude() function's check to be unsynchronized because the only times that this check can evaluate to true is when there is only a single CPU running with preemption disabled.
While in the area, this commit also fixes a minor bug in which a call to synchronize_rcu_tasks_rude() would instead be attributed to synchronize_rcu_tasks().
[ paulmck: Add "synchronize_" prefix and "()" suffix. ]
--- kernel/rcu/tasks.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
kernel/rcu/tasks.h +3 -5
@@ -171,8 +171,9 @@ static void call_rcu_tasks_generic(struct rcu_head *rhp, rcu_callback_t func,static void synchronize_rcu_tasks_generic (struct rcu_tasks *rtp) {/* Complain if the scheduler has not started. */ -WARN_ONCE (rcu_scheduler_active ==RCU_SCHEDULER_INACTIVE , -"synchronize_rcu_tasks called too soon" ); +if (WARN_ONCE (rcu_scheduler_active ==RCU_SCHEDULER_INACTIVE , +"synchronize_%s() called too soon" , rtp->name)) +return ;/* Wait for the grace period. */ wait_rcu_gp (rtp->call_func);
@@ -648,9 +649,6 @@ static void rcu_tasks_be_rude(struct work_struct *work)// Wait for one rude RCU-tasks grace period. static void rcu_tasks_rude_wait_gp (struct rcu_tasks *rtp) { -if (num_online_cpus () <=1 ) -return ;// Fastpath for only one CPU. - rtp->n_ipis +=cpumask_weight (cpu_online_mask);schedule_on_each_cpu (rcu_tasks_be_rude); }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 289/529 wifi: ath11k: debugfs: fix to work with multiple PCI devices
In reply to Greg Kroah-HartmanFrom: Kalle Valo <[email protected]>
[ Upstream commit 323d91d4684d238f6bc3693fed93caf795378fe0 ]
ath11k fails to load if there are multiple ath11k PCI devices with same name:
ath11k_pci 0000:01:00.0: Hardware name qcn9074 hw1.0
debugfs: Directory 'ath11k' with parent '/' already present! ath11k_pci 0000:01:00.0: failed to create ath11k debugfs ath11k_pci 0000:01:00.0: failed to create soc core: -17 ath11k_pci 0000:01:00.0: failed to init core: -17
ath11k_pci: probe of 0000:01:00.0 failed with error -17
Fix this by creating a directory for each ath11k device using schema <bus>-<devname>, for example "pci-0000:06:00.0". This directory created under the top-level ath11k directory, for example /sys/kernel/debug/ath11k.
The reference to the toplevel ath11k directory is not stored anymore within ath11k, instead it's retrieved using debugfs_lookup(). If the directory does not exist it will be created. After the last directory from the ath11k directory is removed, for example when doing rmmod ath11k, the empty ath11k directory is left in place, it's a minor cosmetic issue anyway.
Here's an example hierarchy with one WCN6855:
ath11k
`-- pci-0000:06:00.0
|-- mac0
| |-- dfs_block_radar_events
| |-- dfs_simulate_radar
| |-- ext_rx_stats
| |-- ext_tx_stats
| |-- fw_dbglog_config
| |-- fw_stats
| | |-- beacon_stats
| | |-- pdev_stats
| | `-- vdev_stats
| |-- htt_stats
| |-- htt_stats_reset
| |-- htt_stats_type
| `-- pktlog_filter
|-- simulate_fw_crash
`-- soc_dp_statsI didn't have a test setup where I could connect multiple ath11k devices to the same the host, so I have only tested this with one device.
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.9
Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.5.0.1-01208-QCAHKSWPL_SILICONZ-1
Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.5.0.1-01208-QCAHKSWPL_SILICONZ-1
--- drivers/net/wireless/ath/ath11k/core.h | 1 - drivers/net/wireless/ath/ath11k/debugfs.c | 48 +++++++++++++++++++---- 2 files changed, 40 insertions(+), 9 deletions(-)
drivers/net/wireless/ath/ath11k/core.h +0 -1
@@ -712,7 +712,6 @@ struct ath11k_base {enum ath11k_dfs_region dfs_region;#ifdef CONFIG_ATH11K_DEBUGFS struct dentry *debugfs_soc; -struct dentry *debugfs_ath11k;#endif struct ath11k_soc_dp_stats soc_stats;
drivers/net/wireless/ath/ath11k/debugfs.c +40 -8
65 lines not on this page · raw message
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 290/529 thermal: intel: Fix unsigned comparison with less than zero
In reply to Greg Kroah-HartmanFrom: Yang Li <[email protected]>
[ Upstream commit e7fcfe67f9f410736b758969477b17ea285e8e6c ]
The return value from the call to intel_tcc_get_tjmax() is int, which can be a negative error code. However, the return value is being assigned to an u32 variable 'tj_max', so making 'tj_max' an int.
Eliminate the following warning:
./drivers/thermal/intel/intel_soc_dts_iosf.c:394:5-11: WARNING: Unsigned expression compared with zero: tj_max < 0
--- drivers/thermal/intel/intel_soc_dts_iosf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/thermal/intel/intel_soc_dts_iosf.c +1 -1
@@ -404,7 +404,7 @@ struct intel_soc_dts_sensors *intel_soc_dts_iosf_init( {struct intel_soc_dts_sensors *sensors;bool notification; -u32 tj_max; +int tj_max;int ret;int i;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 291/529 timers: Prevent union confusion from unexpected restart_syscall()
In reply to Greg Kroah-HartmanFrom: Jann Horn <[email protected]>
[ Upstream commit 9f76d59173d9d146e96c66886b671c1915a5c5e5 ]
The nanosleep syscalls use the restart_block mechanism, with a quirk:
The type and rmtp/compat_rmtp fields are set up unconditionally on syscall entry, while the rest of the restart_block is only set up in the unlikely case that the syscall is actually interrupted by a signal (or pseudo-signal) that doesn't have a signal handler.
If the restart_block was set up by a previous syscall (futex(..., FUTEX_WAIT, ...) or poll()) and hasn't been invalidated somehow since then, this will clobber some of the union fields used by futex_wait_restart() and do_restart_poll().
If userspace afterwards wrongly calls the restart_syscall syscall, futex_wait_restart()/do_restart_poll() will read struct fields that have been clobbered.
This doesn't actually lead to anything particularly interesting because none of the union fields contain trusted kernel data, and futex(..., FUTEX_WAIT, ...) and poll() aren't syscalls where it makes much sense to apply seccomp filters to their arguments.
So the current consequences are just of the "if userspace does bad stuff, it can damage itself, and that's not a problem" flavor.
But still, it seems like a hazard for future developers, so invalidate the restart_block when partly setting it up in the nanosleep syscalls.
--- kernel/time/hrtimer.c | 2 ++ kernel/time/posix-stubs.c | 2 ++ kernel/time/posix-timers.c | 2 ++ 3 files changed, 6 insertions(+)
kernel/time/hrtimer.c +2 -0
@@ -2024,6 +2024,7 @@ SYSCALL_DEFINE2(nanosleep, struct __kernel_timespec __user *, rqtp,if (!timespec64_valid (&tu))return -EINVAL ; + current->restart_block.fn = do_no_restart_syscall; current->restart_block.nanosleep.type = rmtp ?TT_NATIVE :TT_NONE ; current->restart_block.nanosleep.rmtp = rmtp; return hrtimer_nanosleep(timespec64_to_ktime(tu), HRTIMER_MODE_REL,
@@ -2045,6 +2046,7 @@ SYSCALL_DEFINE2(nanosleep_time32, struct old_timespec32 __user *, rqtp,if (!timespec64_valid (&tu))return -EINVAL ; + current->restart_block.fn = do_no_restart_syscall; current->restart_block.nanosleep.type = rmtp ?TT_COMPAT :TT_NONE ; current->restart_block.nanosleep.compat_rmtp = rmtp; return hrtimer_nanosleep(timespec64_to_ktime(tu), HRTIMER_MODE_REL,
kernel/time/posix-stubs.c +2 -0
@@ -146,6 +146,7 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,return -EINVAL ;if (flags &TIMER_ABSTIME ) rmtp =NULL ; + current->restart_block.fn = do_no_restart_syscall; current->restart_block.nanosleep.type = rmtp ?TT_NATIVE :TT_NONE ; current->restart_block.nanosleep.rmtp = rmtp; texp =timespec64_to_ktime (t);
@@ -239,6 +240,7 @@ SYSCALL_DEFINE4(clock_nanosleep_time32, clockid_t, which_clock, int, flags,return -EINVAL ;if (flags &TIMER_ABSTIME ) rmtp =NULL ; + current->restart_block.fn = do_no_restart_syscall; current->restart_block.nanosleep.type = rmtp ?TT_COMPAT :TT_NONE ; current->restart_block.nanosleep.compat_rmtp = rmtp; texp =timespec64_to_ktime (t);
kernel/time/posix-timers.c +2 -0
@@ -1270,6 +1270,7 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,return -EINVAL ;if (flags &TIMER_ABSTIME ) rmtp =NULL ; + current->restart_block.fn = do_no_restart_syscall; current->restart_block.nanosleep.type = rmtp ?TT_NATIVE :TT_NONE ; current->restart_block.nanosleep.rmtp = rmtp;
@@ -1297,6 +1298,7 @@ SYSCALL_DEFINE4(clock_nanosleep_time32, clockid_t, which_clock, int, flags,return -EINVAL ;if (flags &TIMER_ABSTIME ) rmtp =NULL ; + current->restart_block.fn = do_no_restart_syscall; current->restart_block.nanosleep.type = rmtp ?TT_COMPAT :TT_NONE ; current->restart_block.nanosleep.compat_rmtp = rmtp;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 292/529 x86/bugs: Reset speculation control settings on init
In reply to Greg Kroah-HartmanFrom: Breno Leitao <[email protected]>
[ Upstream commit 0125acda7d76b943ca55811df40ed6ec0ecf670f ]
Currently, x86_spec_ctrl_base is read at boot time and speculative bits are set if Kconfig items are enabled. For example, IBRS is enabled if CONFIG_CPU_IBRS_ENTRY is configured, etc. These MSR bits are not cleared if the mitigations are disabled.
This is a problem when kexec-ing a kernel that has the mitigation disabled from a kernel that has the mitigation enabled. In this case, the MSR bits are not cleared during the new kernel boot. As a result, this might have some performance degradation that is hard to pinpoint.
This problem does not happen if the machine is (hard) rebooted because the bit will be cleared by default.
[ bp: Massage. ]
--- arch/x86/include/asm/msr-index.h | 4 ++++ arch/x86/kernel/cpu/bugs.c | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-)
arch/x86/include/asm/msr-index.h +4 -0
@@ -54,6 +54,10 @@#define SPEC_CTRL_RRSBA_DIS_S_SHIFT 6/* Disable RRSBA behavior */ #define SPEC_CTRL_RRSBA_DIS_S BIT(SPEC_CTRL_RRSBA_DIS_S_SHIFT) +/* A mask for bits which the kernel toggles when controlling mitigations */ +#define SPEC_CTRL_MITIGATIONS_MASK (SPEC_CTRL_IBRS | SPEC_CTRL_STIBP | SPEC_CTRL_SSBD \ + | SPEC_CTRL_RRSBA_DIS_S) +#define MSR_IA32_PRED_CMD 0x00000049/* Prediction Command */ #define PRED_CMD_IBPB BIT(0)/* Indirect Branch Prediction Barrier */
arch/x86/kernel/cpu/bugs.c +9 -1
@@ -136,9 +136,17 @@ void __init check_bugs(void)* have unknown values. AMD64_LS_CFG MSR is cached in the early AMD * init code as it is not enumerated and depends on the family. */ -if (boot_cpu_has (X86_FEATURE_MSR_SPEC_CTRL )) +if (cpu_feature_enabled (X86_FEATURE_MSR_SPEC_CTRL )) {rdmsrl (MSR_IA32_SPEC_CTRL , x86_spec_ctrl_base); +/* +* Previously running kernel (kexec), may have some controls +* turned ON. Clear them and let the mitigations setup below +* rediscover them based on configuration. +*/ + x86_spec_ctrl_base &= ~SPEC_CTRL_MITIGATIONS_MASK ; + } +/* Select the proper CPU mitigations before patching alternatives: */ spectre_v1_select_mitigation ();spectre_v2_select_mitigation ();
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 293/529 wifi: brcmfmac: ensure CLM version is null-terminated to prevent stack-out-of-bounds
In reply to Greg Kroah-HartmanFrom: Jisoo Jang <[email protected]>
[ Upstream commit 660145d708be52f946a82e5b633c020f58f996de ]
Fix a stack-out-of-bounds read in brcmfmac that occurs when 'buf' that is not null-terminated is passed as an argument of strreplace() in brcmf_c_preinit_dcmds(). This buffer is filled with a CLM version string by memcpy() in brcmf_fil_iovar_data_get(). Ensure buf is null-terminated.
Found by a modified version of syzkaller.
[ 33.004414][ T1896] brcmfmac: brcmf_c_process_clm_blob: no clm_blob available (err=-2), device may have limited channels available [ 33.013486][ T1896] brcmfmac: brcmf_c_preinit_dcmds: Firmware: BCM43236/3 wl0: Nov 30 2011 17:33:42 version 5.90.188.22 [ 33.021554][ T1896] ================================================================== [ 33.022379][ T1896] BUG: KASAN: stack-out-of-bounds in strreplace+0xf2/0x110 [ 33.023122][ T1896] Read of size 1 at addr ffffc90001d6efc8 by task kworker/0:2/1896 [ 33.023852][ T1896] [ 33.024096][ T1896] CPU: 0 PID: 1896 Comm: kworker/0:2 Tainted: G O 5.14.0+ #132 [ 33.024927][ T1896] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014 [ 33.026065][ T1896] Workqueue: usb_hub_wq hub_event [ 33.026581][ T1896] Call Trace: [ 33.026896][ T1896] dump_stack_lvl+0x57/0x7d [ 33.027372][ T1896] print_address_description.constprop.0.cold+0xf/0x334 [ 33.028037][ T1896] ? strreplace+0xf2/0x110 [ 33.028403][ T1896] ? strreplace+0xf2/0x110 [ 33.028807][ T1896] kasan_report.cold+0x83/0xdf [ 33.029283][ T1896] ? strreplace+0xf2/0x110 [ 33.029666][ T1896] strreplace+0xf2/0x110 [ 33.029966][ T1896] brcmf_c_preinit_dcmds+0xab1/0xc40 [ 33.030351][ T1896] ? brcmf_c_set_joinpref_default+0x100/0x100 [ 33.030787][ T1896] ? rcu_read_lock_sched_held+0xa1/0xd0 [ 33.031223][ T1896] ? rcu_read_lock_bh_held+0xb0/0xb0 [ 33.031661][ T1896] ? lock_acquire+0x19d/0x4e0 [ 33.032091][ T1896] ? find_held_lock+0x2d/0x110 [ 33.032605][ T1896] ? brcmf_usb_deq+0x1a7/0x260 [ 33.033087][ T1896] ? brcmf_usb_rx_fill_all+0x5a/0xf0 [ 33.033582][ T1896] brcmf_attach+0x246/0xd40 [ 33.034022][ T1896] ? wiphy_new_nm+0x1476/0x1d50 [ 33.034383][ T1896] ? kmemdup+0x30/0x40 [ 33.034722][ T1896] brcmf_usb_probe+0x12de/0x1690 [ 33.035223][ T1896] ? brcmf_usbdev_qinit.constprop.0+0x470/0x470 [ 33.035833][ T1896] usb_probe_interface+0x25f/0x710 [ 33.036315][ T1896] really_probe+0x1be/0xa90 [ 33.036656][ T1896] __driver_probe_device+0x2ab/0x460 [ 33.037026][ T1896] ? usb_match_id.part.0+0x88/0xc0 [ 33.037383][ T1896] driver_probe_device+0x49/0x120 [ 33.037790][ T1896] __device_attach_driver+0x18a/0x250 [ 33.038300][ T1896] ? driver_allows_async_probing+0x120/0x120 [ 33.038986][ T1896] bus_for_each_drv+0x123/0x1a0 [ 33.039906][ T1896] ? bus_rescan_devices+0x20/0x20 [ 33.041412][ T1896] ? lockdep_hardirqs_on_prepare+0x273/0x3e0 [ 33.041861][ T1896] ? trace_hardirqs_on+0x1c/0x120 [ 33.042330][ T1896] __device_attach+0x207/0x330 [ 33.042664][ T1896] ? device_bind_driver+0xb0/0xb0 [ 33.043026][ T1896] ? kobject_uevent_env+0x230/0x12c0 [ 33.043515][ T1896] bus_probe_device+0x1a2/0x260 [ 33.043914][ T1896] device_add+0xa61/0x1ce0 [ 33.044227][ T1896] ? __mutex_unlock_slowpath+0xe7/0x660 [ 33.044891][ T1896] ? __fw_devlink_link_to_suppliers+0x550/0x550 [ 33.045531][ T1896] usb_set_configuration+0x984/0x1770 [ 33.046051][ T1896] ? kernfs_create_link+0x175/0x230 [ 33.046548][ T1896] usb_generic_driver_probe+0x69/0x90 [ 33.046931][ T1896] usb_probe_device+0x9c/0x220 [ 33.047434][ T1896] really_probe+0x1be/0xa90 [ 33.047760][ T1896] __driver_probe_device+0x2ab/0x460 [ 33.048134][ T1896] driver_probe_device+0x49/0x120 [ 33.048516][ T1896] __device_attach_driver+0x18a/0x250 [ 33.048910][ T1896] ? driver_allows_async_probing+0x120/0x120 [ 33.049437][ T1896] bus_for_each_drv+0x123/0x1a0 [ 33.049814][ T1896] ? bus_rescan_devices+0x20/0x20 [ 33.050164][ T1896] ? lockdep_hardirqs_on_prepare+0x273/0x3e0 [ 33.050579][ T1896] ? trace_hardirqs_on+0x1c/0x120 [ 33.050936][ T1896] __device_attach+0x207/0x330 [ 33.051399][ T1896] ? device_bind_driver+0xb0/0xb0 [ 33.051888][ T1896] ? kobject_uevent_env+0x230/0x12c0 [ 33.052314][ T1896] bus_probe_device+0x1a2/0x260 [ 33.052688][ T1896] device_add+0xa61/0x1ce0 [ 33.053121][ T1896] ? __fw_devlink_link_to_suppliers+0x550/0x550 [ 33.053568][ T1896] usb_new_device.cold+0x463/0xf66 [ 33.053953][ T1896] ? hub_disconnect+0x400/0x400 [ 33.054313][ T1896] ? rwlock_bug.part.0+0x90/0x90 [ 33.054661][ T1896] ? lockdep_hardirqs_on_prepare+0x273/0x3e0 [ 33.055094][ T1896] hub_event+0x10d5/0x3330 [ 33.055530][ T1896] ? hub_port_debounce+0x280/0x280 [ 33.055934][ T1896] ? __lock_acquire+0x1671/0x5790 [ 33.056387][ T1896] ? wq_calc_node_cpumask+0x170/0x2a0 [ 33.056924][ T1896] ? lock_release+0x640/0x640 [ 33.057383][ T1896] ? rcu_read_lock_sched_held+0xa1/0xd0 [ 33.057916][ T1896] ? rcu_read_lock_bh_held+0xb0/0xb0 [ 33.058402][ T1896] ? lockdep_hardirqs_on_prepare+0x273/0x3e0 [ 33.059019][ T1896] process_one_work+0x873/0x13e0 [ 33.059488][ T1896] ? lock_release+0x640/0x640 [ 33.059932][ T1896] ? pwq_dec_nr_in_flight+0x320/0x320 [ 33.060446][ T1896] ? rwlock_bug.part.0+0x90/0x90 [ 33.060898][ T1896] worker_thread+0x8b/0xd10 [ 33.061348][ T1896] ? __kthread_parkme+0xd9/0x1d0 [ 33.061810][ T1896] ? process_one_work+0x13e0/0x13e0 [ 33.062288][ T1896] kthread+0x379/0x450 [ 33.062660][ T1896] ? _raw_spin_unlock_irq+0x24/0x30 [ 33.063148][ T1896] ? set_kthread_struct+0x100/0x100 [ 33.063606][ T1896] ret_from_fork+0x1f/0x30 [ 33.064070][ T1896] [ 33.064313][ T1896] [ 33.064545][ T1896] addr ffffc90001d6efc8 is located in stack of task kworker/0:2/1896 at offset 512 in frame: [ 33.065478][ T1896] brcmf_c_preinit_dcmds+0x0/0xc40 [ 33.065973][ T1896] [ 33.066191][ T1896] this frame has 4 objects: [ 33.066614][ T1896] [48, 56) 'ptr' [ 33.066618][ T1896] [80, 148) 'revinfo' [ 33.066957][ T1896] [192, 210) 'eventmask' [ 33.067338][ T1896] [256, 512) 'buf' [ 33.067742][ T1896] [ 33.068304][ T1896] Memory state around the buggy address: [ 33.068838][ T1896] ffffc90001d6ee80: f2 00 00 02 f2 f2 f2 f2 f2 00 00 00 00 00 00 00 [ 33.069545][ T1896] ffffc90001d6ef00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 33.070626][ T1896] >ffffc90001d6ef80: 00 00 00 00 00 00 00 00 00 f3 f3 f3 f3 f3 f3 f3 [ 33.072052][ T1896] ^ [ 33.073043][ T1896] ffffc90001d6f000: f3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 33.074230][ T1896] ffffc90001d6f080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 33.074914][ T1896] ================================================================== [ 33.075713][ T1896] Disabling lock debugging due to kernel taint
--- drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +4 -2
@@ -281,15 +281,17 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)if (err) {brcmf_dbg (TRACE ,"retrieving clmver failed, %d\n" , err); }else { + buf[sizeof (buf) -1 ] ='\0' ; clmver = (char *)buf; -/* store CLM version for adding it to revinfo debugfs file */ -memcpy (ifp->drvr->clmver, clmver,sizeof (ifp->drvr->clmver));/* Replace all newline/linefeed characters with space * character */ strreplace (clmver,'\n' ,' ' ); +/* store CLM version for adding it to revinfo debugfs file */ +memcpy (ifp->drvr->clmver, clmver,sizeof (ifp->drvr->clmver)); +brcmf_dbg (INFO ,"CLM version = %s\n" , clmver); }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 294/529 wifi: mt7601u: fix an integer underflow
In reply to Greg Kroah-HartmanFrom: Jisoo Jang <[email protected]>
[ Upstream commit 803f3176c5df3b5582c27ea690f204abb60b19b9 ]
Fix an integer underflow that leads to a null pointer dereference in 'mt7601u_rx_skb_from_seg()'. The variable 'dma_len' in the URB packet could be manipulated, which could trigger an integer underflow of 'seg_len' in 'mt7601u_rx_process_seg()'. This underflow subsequently causes the 'bad_frame' checks in 'mt7601u_rx_skb_from_seg()' to be bypassed, eventually leading to a dereference of the pointer 'p', which is a null pointer.
Ensure that 'dma_len' is greater than 'min_seg_len'.
Found by a modified version of syzkaller.
KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f] CPU: 0 PID: 12 Comm: ksoftirqd/0 Tainted: G W O 5.14.0+ #139 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014 RIP: 0010:skb_add_rx_frag+0x143/0x370 Code: e2 07 83 c2 03 38 ca 7c 08 84 c9 0f 85 86 01 00 00 4c 8d 7d 08 44 89 68 08 48 b8 00 00 00 00 00 fc ff df 4c 89 fa 48 c1 ea 03 <80> 3c 02 00 0f 85 cd 01 00 00 48 8b 45 08 a8 01 0f 85 3d 01 00 00 RSP: 0018:ffffc900000cfc90 EFLAGS: 00010202 RAX: dffffc0000000000 RBX: ffff888115520dc0 RCX: 0000000000000000 RDX: 0000000000000001 RSI: ffff8881118430c0 RDI: ffff8881118430f8 RBP: 0000000000000000 R08: 0000000000000e09 R09: 0000000000000010 R10: ffff888111843017 R11: ffffed1022308602 R12: 0000000000000000 R13: 0000000000000e09 R14: 0000000000000010 R15: 0000000000000008 FS: 0000000000000000(0000) GS:ffff88811a800000(0000)
knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000000004035af40 CR3: 00000001157f2000 CR4: 0000000000750ef0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
PKRU: 55555554
Call Trace: mt7601u_rx_tasklet+0xc73/0x1270 ? mt7601u_submit_rx_buf.isra.0+0x510/0x510 ? tasklet_action_common.isra.0+0x79/0x2f0 tasklet_action_common.isra.0+0x206/0x2f0 __do_softirq+0x1b5/0x880 ? tasklet_unlock+0x30/0x30 run_ksoftirqd+0x26/0x50 smpboot_thread_fn+0x34f/0x7d0 ? smpboot_register_percpu_thread+0x370/0x370 kthread+0x3a1/0x480 ? set_kthread_struct+0x120/0x120 ret_from_fork+0x1f/0x30 Modules linked in: 88XXau(O) 88x2bu(O) ---[ end trace 57f34f93b4da0f9b ]--- RIP: 0010:skb_add_rx_frag+0x143/0x370 Code: e2 07 83 c2 03 38 ca 7c 08 84 c9 0f 85 86 01 00 00 4c 8d 7d 08 44 89 68 08 48 b8 00 00 00 00 00 fc ff df 4c 89 fa 48 c1 ea 03 <80> 3c 02 00 0f 85 cd 01 00 00 48 8b 45 08 a8 01 0f 85 3d 01 00 00 RSP: 0018:ffffc900000cfc90 EFLAGS: 00010202 RAX: dffffc0000000000 RBX: ffff888115520dc0 RCX: 0000000000000000 RDX: 0000000000000001 RSI: ffff8881118430c0 RDI: ffff8881118430f8 RBP: 0000000000000000 R08: 0000000000000e09 R09: 0000000000000010 R10: ffff888111843017 R11: ffffed1022308602 R12: 0000000000000000 R13: 0000000000000e09 R14: 0000000000000010 R15: 0000000000000008 FS: 0000000000000000(0000) GS:ffff88811a800000(0000)
knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000000004035af40 CR3: 00000001157f2000 CR4: 0000000000750ef0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
PKRU: 55555554
--- drivers/net/wireless/mediatek/mt7601u/dma.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt7601u/dma.c +2 -1
@@ -118,7 +118,8 @@ static u16 mt7601u_rx_next_seg_len(u8 *data, u32 data_len)if (data_len < min_seg_len ||WARN_ON_ONCE (!dma_len) ||WARN_ON_ONCE (dma_len +MT_DMA_HDRS > data_len) || -WARN_ON_ONCE (dma_len &0x3 )) +WARN_ON_ONCE (dma_len &0x3 ) || +WARN_ON_ONCE (dma_len < min_seg_len))return 0 ;return MT_DMA_HDRS + dma_len;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 295/529 inet: fix fast path in __inet_hash_connect()
In reply to Greg Kroah-HartmanFrom: Pietro Borrello <[email protected]>
[ Upstream commit 21cbd90a6fab7123905386985e3e4a80236b8714 ]
__inet_hash_connect() has a fast path taken if sk_head(&tb->owners) is equal to the sk parameter.sk_head() returns the hlist_entry() with respect to the sk_node field. However entries in the tb->owners list are inserted with respect to the sk_bind_node field with sk_add_bind_node().
Thus the check would never pass and the fast path never execute.
This fast path has never been executed or tested as this bug seems to be present since commit 1da177e4c3f4 ("Linux-2.6.12-rc2"), thus remove it to reduce code complexity.
--- net/ipv4/inet_hashtables.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-)
net/ipv4/inet_hashtables.c +1 -11
@@ -760,17 +760,7 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,u32 index;if (port) { - head = &hinfo->bhash[inet_bhashfn (net, port, - hinfo->bhash_size)]; - tb =inet_csk (sk)->icsk_bind_hash; -spin_lock_bh (&head->lock); -if (sk_head (&tb->owners) == sk && !sk->sk_bind_node.next) { -inet_ehash_nolisten (sk,NULL ,NULL ); -spin_unlock_bh (&head->lock); -return 0 ; - } -spin_unlock (&head->lock); -/* No definite answer... Walk to established hash table */ +local_bh_disable (); ret =check_established (death_row, sk, port,NULL );local_bh_enable ();return ret;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 296/529 ice: add missing checks for PF vsi type
In reply to Greg Kroah-HartmanFrom: Jesse Brandeburg <[email protected]>
[ Upstream commit 6a8d013e904ad9a66706fcc926ec9993bed7d190 ]
There were a few places we had missed checking the VSI type to make sure it was definitely a PF VSI, before calling setup functions intended only for the PF VSI.
This doesn't fix any explicit bugs but cleans up the code in a few places and removes one explicit != vsi->type check that can be superseded by this code (it's a super set)
--- drivers/net/ethernet/intel/ice/ice_main.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-)
drivers/net/ethernet/intel/ice/ice_main.c +8 -9
@@ -5200,15 +5200,12 @@ int ice_vsi_cfg(struct ice_vsi *vsi) {int err; -if (vsi->netdev) { +if (vsi->netdev && vsi->type ==ICE_VSI_PF ) {ice_set_rx_mode (vsi->netdev); -if (vsi->type !=ICE_VSI_LB ) { - err =ice_vsi_vlan_setup (vsi); - -if (err) -return err; - } + err =ice_vsi_vlan_setup (vsi); +if (err) +return err; }ice_vsi_cfg_dcb_rings (vsi);
@@ -5267,7 +5264,7 @@ static int ice_up_complete(struct ice_vsi *vsi)if (vsi->port_info && (vsi->port_info->phy.link_info.link_info &ICE_AQ_LINK_UP ) && - vsi->netdev) { + vsi->netdev && vsi->type ==ICE_VSI_PF ) {ice_print_link_msg (vsi, true);netif_tx_start_all_queues (vsi->netdev);netif_carrier_on (vsi->netdev);
@@ -5277,7 +5274,9 @@ static int ice_up_complete(struct ice_vsi *vsi)* set the baseline so counters are ready when interface is up */ ice_update_eth_stats (vsi); -ice_service_task_schedule (pf); + +if (vsi->type ==ICE_VSI_PF ) +ice_service_task_schedule (pf);return 0 ; }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 297/529 ACPI: Dont build ACPICA with -Os
In reply to Greg Kroah-HartmanFrom: Mark Rutland <[email protected]>
[ Upstream commit 8f9e0a52810dd83406c768972d022c37e7a18f1f ]
The ACPICA code has been built with '-Os' since the beginning of git history, though there's no explanatory comment as to why.
This is unfortunate as GCC drops the alignment specificed by '-falign-functions=N' when '-Os' is used, as reported in GCC bug 88345:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88345
This prevents CONFIG_FUNCTION_ALIGNMENT and CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B from having their expected effect on the ACPICA code. This is doubly unfortunate as in subsequent patches arm64 will depend upon CONFIG_FUNCTION_ALIGNMENT for its ftrace implementation.
Drop the '-Os' flag when building the ACPICA code. With this removed, the code builds cleanly and works correctly in testing so far.
I've tested this by selecting CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B=y, building and booting a kernel using ACPI, and looking for misaligned text symbols:
* arm64:
Before, v6.2-rc3:
# uname -rm
6.2.0-rc3 aarch64
# grep ' [Tt] ' /proc/kallsyms | grep -iv '[048c]0 [Tt] ' | wc -l
5009 Before, v6.2-rc3 + fixed __cold:
# uname -rm
6.2.0-rc3-00001-g2a2bedf8bfa9 aarch64
# grep ' [Tt] ' /proc/kallsyms | grep -iv '[048c]0 [Tt] ' | wc -l
919After:
# uname -rm
6.2.0-rc3-00002-g267bddc38572 aarch64
# grep ' [Tt] ' /proc/kallsyms | grep -iv '[048c]0 [Tt] ' | wc -l
323
# grep ' [Tt] ' /proc/kallsyms | grep -iv '[048c]0 [Tt] ' | grep acpi | wc -l
0* x86_64:
Before, v6.2-rc3:
# uname -rm
6.2.0-rc3 x86_64
# grep ' [Tt] ' /proc/kallsyms | grep -iv '[048c]0 [Tt] ' | wc -l
11537 Before, v6.2-rc3 + fixed __cold:
# uname -rm
6.2.0-rc3-00001-g2a2bedf8bfa9 x86_64
# grep ' [Tt] ' /proc/kallsyms | grep -iv '[048c]0 [Tt] ' | wc -l
2805After:
# uname -rm
6.2.0-rc3-00002-g267bddc38572 x86_64
# grep ' [Tt] ' /proc/kallsyms | grep -iv '[048c]0 [Tt] ' | wc -l
1357
# grep ' [Tt] ' /proc/kallsyms | grep -iv '[048c]0 [Tt] ' | grep acpi | wc -l
0With the patch applied, the remaining unaligned text labels are a combination of static call trampolines and labels in assembly, which can be dealt with in subsequent patches.
--- drivers/acpi/acpica/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/acpica/Makefile +1 -1
@@ -3,7 +3,7 @@ # Makefile for ACPICA Core interpreter # -ccflags-y := -Os -D_LINUX -DBUILDING_ACPICA +ccflags-y := -D_LINUX -DBUILDING_ACPICA ccflags-$(CONFIG_ACPI_DEBUG) += -DACPI_DEBUG_OUTPUT # use acpi.o to put all files here into acpi.o modparam namespace
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 298/529 clocksource: Suspend the watchdog temporarily when high read latency detected
In reply to Greg Kroah-HartmanFrom: Feng Tang <[email protected]>
[ Upstream commit b7082cdfc464bf9231300605d03eebf943dda307 ]
Bugs have been reported on 8 sockets x86 machines in which the TSC was wrongly disabled when the system is under heavy workload.
[ 818.380354] clocksource: timekeeping watchdog on CPU336: hpet wd-wd read-back delay of 1203520ns [ 818.436160] clocksource: wd-tsc-wd read-back delay of 181880ns, clock-skew test skipped! [ 819.402962] clocksource: timekeeping watchdog on CPU338: hpet wd-wd read-back delay of 324000ns [ 819.448036] clocksource: wd-tsc-wd read-back delay of 337240ns, clock-skew test skipped! [ 819.880863] clocksource: timekeeping watchdog on CPU339: hpet read-back delay of 150280ns, attempt 3, marking unstable [ 819.936243] tsc: Marking TSC unstable due to clocksource watchdog [ 820.068173] TSC found unstable after boot, most likely due to broken BIOS. Use 'tsc=unstable'. [ 820.092382] sched_clock: Marking unstable (818769414384, 1195404998) [ 820.643627] clocksource: Checking clocksource tsc synchronization from CPU 267 to CPUs 0,4,25,70,126,430,557,564. [ 821.067990] clocksource: Switched to clocksource hpet
This can be reproduced by running memory intensive 'stream' tests, or some of the stress-ng subcases such as 'ioport'.
The reason for these issues is the when system is under heavy load, the read latency of the clocksources can be very high. Even lightweight TSC reads can show high latencies, and latencies are much worse for external clocksources such as HPET or the APIC PM timer. These latencies can result in false-positive clocksource-unstable determinations.
These issues were initially reported by a customer running on a production system, and this problem was reproduced on several generations of Xeon servers, especially when running the stress-ng test. These Xeon servers were not production systems, but they did have the latest steppings and firmware.
Given that the clocksource watchdog is a continual diagnostic check with frequency of twice a second, there is no need to rush it when the system is under heavy load. Therefore, when high clocksource read latencies are detected, suspend the watchdog timer for 5 minutes.
--- kernel/time/clocksource.c | 45 ++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 13 deletions(-)
kernel/time/clocksource.c +32 -13
@@ -312,6 +312,15 @@ static void clocksource_verify_percpu(struct clocksource *cs) testcpu, cs_nsec_min, cs_nsec_max, cs->name); } +static inline void clocksource_reset_watchdog (void ) +{ +struct clocksource *cs; + +list_for_each_entry (cs, &watchdog_list, wd_list) + cs->flags &= ~CLOCK_SOURCE_WATCHDOG ; +} + +static void clocksource_watchdog (struct timer_list *unused) {u64 csnow, wdnow, cslast, wdlast, delta;
@@ -319,6 +328,7 @@ static void clocksource_watchdog(struct timer_list *unused)int64_t wd_nsec, cs_nsec;struct clocksource *cs;enum wd_read_status read_ret; +unsigned long extra_wait =0 ;u32 md;spin_lock (&watchdog_lock);
@@ -338,13 +348,30 @@ static void clocksource_watchdog(struct timer_list *unused) read_ret =cs_watchdog_read (cs, &csnow, &wdnow); -if (read_ret !=WD_READ_SUCCESS ) { -if (read_ret ==WD_READ_UNSTABLE ) -/* Clock readout unreliable, so give it up. */ -__clocksource_unstable (cs); +if (read_ret ==WD_READ_UNSTABLE ) { +/* Clock readout unreliable, so give it up. */ +__clocksource_unstable (cs);continue ; } +/* +* When WD_READ_SKIP is returned, it means the system is likely +* under very heavy load, where the latency of reading +* watchdog/clocksource is very big, and affect the accuracy of +* watchdog check. So give system some space and suspend the +* watchdog check for 5 minutes. +*/ +if (read_ret ==WD_READ_SKIP ) { +/* +* As the watchdog timer will be suspended, and +* cs->last could keep unchanged for 5 minutes, reset +* the counters. +*/ +clocksource_reset_watchdog (); + extra_wait =HZ *300 ; +break ; + } +/* Clocksource initialized ? */ if (!(cs->flags &CLOCK_SOURCE_WATCHDOG ) ||atomic_read (&watchdog_reset_pending)) {
@@ -434,7 +461,7 @@ static void clocksource_watchdog(struct timer_list *unused)* pair clocksource_stop_watchdog() clocksource_start_watchdog(). */ if (!timer_pending (&watchdog_timer)) { - watchdog_timer.expires +=WATCHDOG_INTERVAL ; + watchdog_timer.expires +=WATCHDOG_INTERVAL + extra_wait;add_timer_on (&watchdog_timer, next_cpu); } out:
@@ -459,14 +486,6 @@ static inline void clocksource_stop_watchdog(void) watchdog_running =0 ; } -static inline void clocksource_reset_watchdog (void ) -{ -struct clocksource *cs; - -list_for_each_entry (cs, &watchdog_list, wd_list) - cs->flags &= ~CLOCK_SOURCE_WATCHDOG ; -} -static void clocksource_resume_watchdog (void ) {atomic_inc (&watchdog_reset_pending);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 299/529 crypto: hisilicon: Wipe entire pool on error
In reply to Greg Kroah-HartmanFrom: Kees Cook <[email protected]>
[ Upstream commit aa85923a954e7704bc9d3847dabeb8540aa98d13 ]
To work around a Clang __builtin_object_size bug that shows up under CONFIG_FORTIFY_SOURCE and UBSAN_BOUNDS, move the per-loop-iteration mem_block wipe into a single wipe of the entire pool structure after the loop.
--- drivers/crypto/hisilicon/sgl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/crypto/hisilicon/sgl.c +1 -2
@@ -113,9 +113,8 @@ struct hisi_acc_sgl_pool *hisi_acc_create_sgl_pool(struct device *dev,for (j =0 ; j < i; j++) {dma_free_coherent (dev, block_size, block[j].sgl, block[j].sgl_dma); -memset (block + j,0 ,sizeof (*block)); } -kfree (pool); +kfree_sensitive (pool);return ERR_PTR (-ENOMEM ); }EXPORT_SYMBOL_GPL (hisi_acc_create_sgl_pool);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 300/529 net: bcmgenet: Add a check for oversized packets
In reply to Greg Kroah-HartmanFrom: Florian Fainelli <[email protected]>
[ Upstream commit 5c0862c2c962052ed5055220a00ac1cefb92fbcd ]
Occasionnaly we may get oversized packets from the hardware which exceed the nomimal 2KiB buffer size we allocate SKBs with. Add an early check which drops the packet to avoid invoking skb_over_panic() and move on to processing the next packet.
--- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/net/ethernet/broadcom/genet/bcmgenet.c +8 -0
@@ -2263,6 +2263,14 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring, __func__, p_index, ring->c_index, ring->read_ptr, dma_length_status); +if (unlikely (len >RX_BUF_LENGTH )) { +netif_err (priv, rx_status, dev,"oversized packet\n" ); + dev->stats.rx_length_errors++; + dev->stats.rx_errors++; +dev_kfree_skb_any (skb); + goto next; + } +if (unlikely (!(dma_flag &DMA_EOP ) || !(dma_flag &DMA_SOP ))) {netif_err (priv, rx_status, dev,"dropping fragmented packet!\n" );
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 301/529 m68k: Check syscall_trace_enter() return code
In reply to Greg Kroah-HartmanFrom: Michael Schmitz <[email protected]>
[ Upstream commit 2ca8a1de4437f21562e57f9ac123914747a8e7a1 ]
Check return code of syscall_trace_enter(), and skip syscall if -1. Return code will be left at what had been set by ptrace or seccomp (in regs->d0).
No regression seen in testing with strace on ARAnyM.
--- arch/m68k/68000/entry.S | 2 ++ arch/m68k/coldfire/entry.S | 2 ++ arch/m68k/kernel/entry.S | 3 +++ 3 files changed, 7 insertions(+)
arch/m68k/68000/entry.S +2 -0
@@ -47,6 +47,8 @@ do_trace: jbsr syscall_trace_enter RESTORE_SWITCH_STACK addql #4,%sp + addql #1,%d0 + jeq ret_from_exception movel %sp@(PT_OFF_ORIG_D0),%d1 movel #-ENOSYS,%d0 cmpl #NR_syscalls,%d1
arch/m68k/coldfire/entry.S +2 -0
@@ -92,6 +92,8 @@ ENTRY(system_call) jbsr syscall_trace_enter RESTORE_SWITCH_STACK addql #4,%sp + addql #1,%d0 + jeq ret_from_exception movel %d3,%a0 jbsr %a0@ movel %d0,%sp@(PT_OFF_D0) /* save the return value */
arch/m68k/kernel/entry.S +3 -0
@@ -167,9 +167,12 @@ do_trace_entry: jbsr syscall_trace RESTORE_SWITCH_STACK addql #4,%sp + addql #1,%d0 | optimization for cmpil #-1,%d0 + jeq ret_from_syscall movel %sp@(PT_OFF_ORIG_D0),%d0 cmpl #NR_syscalls,%d0 jcs syscall + jra ret_from_syscall badsys: movel #-ENOSYS,%sp@(PT_OFF_D0) jra ret_from_syscall
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 302/529 wifi: mt76: dma: free rx_head in mt76_dma_rx_cleanup
In reply to Greg Kroah-HartmanFrom: Lorenzo Bianconi <[email protected]>
[ Upstream commit 1b88b47e898edef0e56e3a2f4e49f052a136153d ]
Free rx_head skb in mt76_dma_rx_cleanup routine in order to avoid possible memory leak at module unload.
--- drivers/net/wireless/mediatek/mt76/dma.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
drivers/net/wireless/mediatek/mt76/dma.c +7 -6
@@ -476,6 +476,7 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)bool more;spin_lock_bh (&q->lock); + do { buf = mt76_dma_dequeue(dev, q, true, NULL, NULL, &more); if (!buf)
@@ -483,6 +484,12 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)skb_free_frag (buf); }while (1 ); + +if (q->rx_head) { +dev_kfree_skb (q->rx_head); + q->rx_head =NULL ; + } +spin_unlock_bh (&q->lock);if (!q->rx_page.va)
@@ -505,12 +512,6 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)mt76_dma_rx_cleanup (dev, q);mt76_dma_sync_idx (dev, q);mt76_dma_rx_fill (dev, q); - -if (!q->rx_head) -return ; - -dev_kfree_skb (q->rx_head); - q->rx_head =NULL ; } static void
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 303/529 ACPI: video: Fix Lenovo Ideapad Z570 DMI match
In reply to Greg Kroah-HartmanFrom: Hans de Goede <[email protected]>
[ Upstream commit 2d11eae42d52a131f06061015e49dc0f085c5bfc ]
Multiple Ideapad Z570 variants need acpi_backlight=native to force native use on these pre Windows 8 machines since acpi_video backlight control does not work here.
The original DMI quirk matches on a product_name of "102434U" but other variants may have different product_name-s such as e.g. "1024D9U".
Move to checking product_version instead as is more or less standard for Lenovo DMI quirks for similar reasons.
--- drivers/acpi/video_detect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/video_detect.c +1 -1
@@ -313,7 +313,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = { .ident = "Lenovo Ideapad Z570", .matches = {DMI_MATCH (DMI_SYS_VENDOR ,"LENOVO" ), - DMI_MATCH(DMI_PRODUCT_NAME, "102434U"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Ideapad Z570"), }, }, {
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 304/529 net/mlx5: fw_tracer: Fix debug print
In reply to Greg Kroah-HartmanFrom: Shay Drory <[email protected]>
[ Upstream commit 988c2352273997a242f15c4fc3711773515006a2 ]
The debug message specify tdsn, but takes as an argument the tmsn. The correct argument is tmsn, hence, fix the print.
--- drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +1 -1
@@ -603,7 +603,7 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, }else { cur_string =mlx5_tracer_message_get (tracer, tracer_event);if (!cur_string) { -pr_debug ("%s Got string event for unknown string tdsm: %d\n" , +pr_debug ("%s Got string event for unknown string tmsn: %d\n" , __func__, tracer_event->string_event.tmsn);return -1 ; }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 305/529 coda: Avoid partial allocation of sig_inputArgs
In reply to Greg Kroah-HartmanFrom: Kees Cook <[email protected]>
[ Upstream commit 48df133578c70185a95a49390d42df1996ddba2a ]
GCC does not like having a partially allocated object, since it cannot reason about it for bounds checking when it is passed to other code. Instead, fully allocate sig_inputArgs. (Alternatively, sig_inputArgs should be defined as a struct coda_in_hdr, if it is actually not using any other part of the union.) Seen under GCC 13:
../fs/coda/upcall.c: In function 'coda_upcall':../fs/coda/upcall.c:801:22: warning: array subscript 'union inputArgs[0]' is partly outside array bounds of 'unsigned char[20]' [-Warray-bounds=]
801 | sig_inputArgs->ih.opcode = CODA_SIGNAL;
| ^~
--- fs/coda/upcall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/coda/upcall.c +1 -1
@@ -790,7 +790,7 @@ static int coda_upcall(struct venus_comm *vcp, sig_req =kmalloc (sizeof (struct upc_req ),GFP_KERNEL );if (!sig_req) goto exit; - sig_inputArgs =kvzalloc (sizeof (struct coda_in_hdr ),GFP_KERNEL ); + sig_inputArgs =kvzalloc (sizeof (*sig_inputArgs),GFP_KERNEL );if (!sig_inputArgs) {kfree (sig_req); goto exit;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 306/529 uaccess: Add minimum bounds check on kernel buffer size
In reply to Greg Kroah-HartmanFrom: Kees Cook <[email protected]>
[ Upstream commit 04ffde1319a715bd0550ded3580d4ea3bc003776 ]
While there is logic about the difference between ksize and usize, copy_struct_from_user() didn't check the size of the destination buffer (when it was known) against ksize. Add this check so there is an upper bounds check on the possible memset() call, otherwise lower bounds checks made by callers will trigger bounds warnings under -Warray-bounds. Seen under GCC 13:
In function 'copy_struct_from_user',
inlined from 'iommufd_fops_ioctl' at../drivers/iommu/iommufd/main.c:333:8:../include/linux/fortify-string.h:59:33: warning: '__builtin_memset' offset [57, 4294967294] is out of the bounds [0, 56] of object 'buf' with type 'union ucmd_buffer' [-Warray-bounds=]
59 | #define __underlying_memset __builtin_memset
| ^
../include/linux/fortify-string.h:453:9: note: in expansion of macro '__underlying_memset'
453 | __underlying_memset(p, c, __fortify_size); \
| ^~~~~~~~~~~~~~~~~~~
../include/linux/fortify-string.h:461:25: note: in expansion of macro '__fortify_memset_chk'
461 | #define memset(p, c, s) __fortify_memset_chk(p, c, s, \
| ^~~~~~~~~~~~~~~~~~~~
../include/linux/uaccess.h:334:17: note: in expansion of macro 'memset'
334 | memset(dst + size, 0, rest);
| ^~~~~~../drivers/iommu/iommufd/main.c: In function 'iommufd_fops_ioctl':../drivers/iommu/iommufd/main.c:311:27: note: 'buf' declared here
311 | union ucmd_buffer buf;
| ^~~
--- include/linux/uaccess.h | 4 ++++ 1 file changed, 4 insertions(+)
include/linux/uaccess.h +4 -0
@@ -348,6 +348,10 @@ copy_struct_from_user(void *dst, size_t ksize, const void __user *src,size_t size =min (ksize, usize);size_t rest =max (ksize, usize) - size; +/* Double check if ksize is larger than a known object size. */ +if (WARN_ON_ONCE (ksize >__builtin_object_size (dst,1 ))) +return -E2BIG ; +/* Deal with trailing bytes. */ if (usize < ksize) {memset (dst + size,0 , rest);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 307/529 PM: EM: fix memory leak with using debugfs_lookup()
In reply to Greg Kroah-HartmanFrom: Greg Kroah-Hartman <[email protected]>
[ Upstream commit a0e8c13ccd6a9a636d27353da62c2410c4eca337 ]
When calling debugfs_lookup() the result must have dput() called on it, otherwise the memory will leak over time. To make things simpler, just call debugfs_lookup_and_remove() instead which handles all of the logic at once.
--- kernel/power/energy_model.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
kernel/power/energy_model.c +1 -4
@@ -72,10 +72,7 @@ static void em_debug_create_pd(struct device *dev)static void em_debug_remove_pd (struct device *dev) { -struct dentry *debug_dir; - - debug_dir =debugfs_lookup (dev_name (dev), rootdir); -debugfs_remove_recursive (debug_dir); +debugfs_lookup_and_remove (dev_name (dev), rootdir); }static int __init em_debug_init (void )
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 308/529 Bluetooth: btusb: Add VID:PID 13d3:3529 for Realtek RTL8821CE
In reply to Greg Kroah-HartmanFrom: Moises Cardona <[email protected]>
[ Upstream commit 1eec3b95b5ce7fb2cdd273ac4f8b24b1ed6776a1 ]
This patch adds VID:PID 13d3:3529 to the btusb.c file.
This VID:PID is found in the Realtek RTL8821CE module (M.2 module AW-CB304NF on an ASUS E210MA laptop)
Output of /sys/kernel/debug/usb/devices:
T: Bus=01 Lev=01 Prnt=01 Port=07 Cnt=02 Dev#= 3 Spd=12 MxCh= 0 D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=13d3 ProdID=3529 Rev= 1.10 S: Manufacturer=Realtek S: Product=Bluetooth Radio C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=500mA I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
--- drivers/bluetooth/btusb.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/bluetooth/btusb.c +4 -0
@@ -393,6 +393,10 @@ static const struct usb_device_id blacklist_table[] = { { USB_VENDOR_AND_INTERFACE_INFO(0x8087, 0xe0, 0x01, 0x01), .driver_info = BTUSB_IGNORE }, + /* Realtek 8821CE Bluetooth devices */ + { USB_DEVICE(0x13d3, 0x3529), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, + /* Realtek 8822CE Bluetooth devices */ { USB_DEVICE(0x0bda, 0xb00c), .driver_info = BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH },
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 309/529 drm/amd/display: Fix potential null-deref in dm_resume
In reply to Greg Kroah-HartmanFrom: Roman Li <[email protected]>
[ Upstream commit 7a7175a2cd84b7874bebbf8e59f134557a34161b ]
[Why]
Fixing smatch error:dm_resume() error: we previously assumed 'aconnector->dc_link' could be null
[How]
Check if dc_link null at the beginning of the loop, so further checks can be dropped.
--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +4 -2
@@ -2051,12 +2051,14 @@ static int dm_resume(void *handle)drm_for_each_connector_iter (connector, &iter) { aconnector =to_amdgpu_dm_connector (connector); +if (!aconnector->dc_link) +continue ; +/* * this is the case when traversing through already created * MST connectors, should be skipped */ -if (aconnector->dc_link && - aconnector->dc_link->type == dc_connection_mst_branch) +if (aconnector->dc_link->type == dc_connection_mst_branch)continue ;mutex_lock (&aconnector->hpd_lock);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 310/529 drm/omap: dsi: Fix excessive stack usage
In reply to Greg Kroah-HartmanFrom: Tomi Valkeinen <[email protected]>
[ Upstream commit cfca78971b9233aef0891507a98fba62046d4542 ]
dsi_dump_dsi_irqs(), a function used for debugfs prints, has a large struct in its frame, which can result in:
drivers/gpu/drm/omapdrm/dss/dsi.c:1126:1: warning: the frame size of 1060 bytes is larger than 1024 bytes [-Wframe-larger-than=]
As the performance of the function is of no concern, let's allocate the struct with kmalloc instead.
Compile-tested only.
--- drivers/gpu/drm/omapdrm/dss/dsi.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-)
drivers/gpu/drm/omapdrm/dss/dsi.c +16 -10
@@ -1444,22 +1444,26 @@ static int dsi_dump_dsi_irqs(struct seq_file *s, void *p) {struct dsi_data *dsi = s->private;unsigned long flags; -struct dsi_irq_stats stats; +struct dsi_irq_stats *stats; + + stats =kmalloc (sizeof (*stats),GFP_KERNEL ); +if (!stats) +return -ENOMEM ;spin_lock_irqsave (&dsi->irq_stats_lock, flags); - stats = dsi->irq_stats; + *stats = dsi->irq_stats;memset (&dsi->irq_stats,0 ,sizeof (dsi->irq_stats)); dsi->irq_stats.last_reset = jiffies;spin_unlock_irqrestore (&dsi->irq_stats_lock, flags);seq_printf (s,"period %u ms\n" , -jiffies_to_msecs (jiffies - stats.last_reset)); +jiffies_to_msecs (jiffies - stats->last_reset)); -seq_printf (s,"irqs %d\n" , stats.irq_count); +seq_printf (s,"irqs %d\n" , stats->irq_count);#define PIS (x) \ - seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]); + seq_printf(s, "%-20s %10d\n", #x, stats->dsi_irqs[ffs(DSI_IRQ_##x)-1]);seq_printf (s,"-- DSI%d interrupts --\n" , dsi->module_id +1 );PIS (VC0 );
@@ -1483,10 +1487,10 @@ static int dsi_dump_dsi_irqs(struct seq_file *s, void *p)#define PIS (x) \ seq_printf(s, "%-20s %10d %10d %10d %10d\n", #x, \ - stats.vc_irqs[0][ffs(DSI_VC_IRQ_##x)-1], \ - stats.vc_irqs[1][ffs(DSI_VC_IRQ_##x)-1], \ - stats.vc_irqs[2][ffs(DSI_VC_IRQ_##x)-1], \ - stats.vc_irqs[3][ffs(DSI_VC_IRQ_##x)-1]); + stats->vc_irqs[0][ffs(DSI_VC_IRQ_##x)-1], \ + stats->vc_irqs[1][ffs(DSI_VC_IRQ_##x)-1], \ + stats->vc_irqs[2][ffs(DSI_VC_IRQ_##x)-1], \ + stats->vc_irqs[3][ffs(DSI_VC_IRQ_##x)-1]);seq_printf (s,"-- VC interrupts --\n" );PIS (CS );
@@ -1502,7 +1506,7 @@ static int dsi_dump_dsi_irqs(struct seq_file *s, void *p)#define PIS (x) \ seq_printf(s, "%-20s %10d\n", #x, \ - stats.cio_irqs[ffs(DSI_CIO_IRQ_##x)-1]); + stats->cio_irqs[ffs(DSI_CIO_IRQ_##x)-1]);seq_printf (s,"-- CIO interrupts --\n" );PIS (ERRSYNCESC1 );
@@ -1527,6 +1531,8 @@ static int dsi_dump_dsi_irqs(struct seq_file *s, void *p)PIS (ULPSACTIVENOT_ALL1 );#undef PIS +kfree (stats); + return 0; }#endif
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 311/529 HID: Add Mapping for System Microphone Mute
In reply to Greg Kroah-HartmanFrom: Jingyuan Liang <[email protected]>
[ Upstream commit 2d60f9f4f26785a00273cb81fe60eff129ebd449 ]
HUTRR110 added a new usage code for a key that is supposed to mute/unmute microphone system-wide.
Map the new usage code(0x01 0xa9) to keycode KEY_MICMUTE. Additionally hid-debug is adjusted to recognize this keycode as well.
--- drivers/hid/hid-debug.c | 1 + drivers/hid/hid-input.c | 8 ++++++++ 2 files changed, 9 insertions(+)
drivers/hid/hid-debug.c +1 -0
@@ -933,6 +933,7 @@ static const char *keys[KEY_MAX + 1] = { [KEY_VOICECOMMAND] = "VoiceCommand", [KEY_EMOJI_PICKER] = "EmojiPicker", [KEY_DICTATE] = "Dictate", + [KEY_MICMUTE] = "MicrophoneMute", [KEY_BRIGHTNESS_MIN] = "BrightnessMin", [KEY_BRIGHTNESS_MAX] = "BrightnessMax", [KEY_BRIGHTNESS_AUTO] = "BrightnessAuto",
drivers/hid/hid-input.c +8 -0
@@ -675,6 +675,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fielbreak ; } +if ((usage->hid &0xf0 ) ==0xa0 ) {/* SystemControl */ +switch (usage->hid &0xf ) { +case 0x9 :map_key_clear (KEY_MICMUTE );break ; +default : goto ignore; + } +break ; + } +if ((usage->hid &0xf0 ) ==0xb0 ) {/* SC - Display */ switch (usage->hid &0xf ) {case 0x05 :map_key_clear (KEY_SWITCHVIDEOMODE );break ;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 312/529 drm/tiny: ili9486: Do not assume 8-bit only SPI controllers
In reply to Greg Kroah-HartmanFrom: Carlo Caione <[email protected]>
[ Upstream commit 77772e607522daa61f3af74df018559db75c43d6 ]
The pixel data for the ILI9486 is always 16-bits wide and it must be sent over the SPI bus. When the controller is only able to deal with 8-bit transfers, this 16-bits data needs to be swapped before the sending to account for the big endian bus, this is on the contrary not needed when the SPI controller already supports 16-bits transfers.
The decision about swapping the pixel data or not is taken in the MIPI DBI code by probing the controller capabilities: if the controller only suppors 8-bit transfers the data is swapped, otherwise it is not.
This swapping/non-swapping is relying on the assumption that when the controller does support 16-bit transactions then the data is sent unswapped in 16-bits-per-word over SPI.
The problem with the ILI9486 driver is that it is forcing 8-bit transactions also for controllers supporting 16-bits, violating the assumption and corrupting the pixel data.
Align the driver to what is done in the MIPI DBI code by adjusting the transfer size to the maximum allowed by the SPI controller.
--- drivers/gpu/drm/tiny/ili9486.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
drivers/gpu/drm/tiny/ili9486.c +9 -4
@@ -43,6 +43,7 @@ static int waveshare_command(struct mipi_dbi *mipi, u8 *cmd, u8 *par, size_t num) {struct spi_device *spi = mipi->spi; +unsigned int bpw =8 ;void *data = par;u32 speed_hz;int i, ret;
@@ -56,8 +57,6 @@ static int waveshare_command(struct mipi_dbi *mipi, u8 *cmd, u8 *par,* The displays are Raspberry Pi HATs and connected to the 8-bit only * SPI controller, so 16-bit command and parameters need byte swapping * before being transferred as 8-bit on the big endian SPI bus. -* Pixel data bytes have already been swapped before this function is -* called. */ buf[0 ] =cpu_to_be16 (*cmd);gpiod_set_value_cansleep (mipi->dc,0 );
@@ -71,12 +70,18 @@ static int waveshare_command(struct mipi_dbi *mipi, u8 *cmd, u8 *par,for (i =0 ; i < num; i++) buf[i] =cpu_to_be16 (par[i]); num *=2 ; - speed_hz =mipi_dbi_spi_cmd_max_speed (spi, num); data = buf; } +/* +* Check whether pixel data bytes needs to be swapped or not +*/ +if (*cmd ==MIPI_DCS_WRITE_MEMORY_START && !mipi->swap_bytes) + bpw =16 ; +gpiod_set_value_cansleep (mipi->dc,1 ); - ret =mipi_dbi_spi_transfer (spi, speed_hz,8 , data, num); + speed_hz =mipi_dbi_spi_cmd_max_speed (spi, num); + ret =mipi_dbi_spi_transfer (spi, speed_hz, bpw, data, num); free:kfree (buf);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 313/529 drm/radeon: free iio for atombios when driver shutdown
In reply to Greg Kroah-HartmanFrom: Liwei Song <[email protected]>
[ Upstream commit 4773fadedca918faec443daaca5e4ea1c0ced144 ]
Fix below kmemleak when unload radeon driver:
unreferenced object 0xffff9f8608ede200 (size 512):
comm "systemd-udevd", pid 326, jiffies 4294682822 (age 716.338s) hex dump (first 32 bytes):
00 00 00 00 c4 aa ec aa 14 ab 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
backtrace:
[<0000000062fadebe>] kmem_cache_alloc_trace+0x2f1/0x500
[<00000000b6883cea>] atom_parse+0x117/0x230 [radeon]
[<00000000158c23fd>] radeon_atombios_init+0xab/0x170 [radeon]
[<00000000683f672e>] si_init+0x57/0x750 [radeon]
[<00000000566cc31f>] radeon_device_init+0x559/0x9c0 [radeon]
[<0000000046efabb3>] radeon_driver_load_kms+0xc1/0x1a0 [radeon]
[<00000000b5155064>] drm_dev_register+0xdd/0x1d0
[<0000000045fec835>] radeon_pci_probe+0xbd/0x100 [radeon]
[<00000000e69ecca3>] pci_device_probe+0xe1/0x160
[<0000000019484b76>] really_probe.part.0+0xc1/0x2c0
[<000000003f2649da>] __driver_probe_device+0x96/0x130
[<00000000231c5bb1>] driver_probe_device+0x24/0xf0
[<0000000000a42377>] __driver_attach+0x77/0x190
[<00000000d7574da6>] bus_for_each_dev+0x7f/0xd0
[<00000000633166d2>] driver_attach+0x1e/0x30
[<00000000313b05b8>] bus_add_driver+0x12c/0x1e0iio was allocated in atom_index_iio() called by atom_parse(), but it doesn't got released when the dirver is shutdown. Fix this kmemleak by free it in radeon_atombios_fini().
--- drivers/gpu/drm/radeon/radeon_device.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/radeon/radeon_device.c +1 -0
@@ -1022,6 +1022,7 @@ void radeon_atombios_fini(struct radeon_device *rdev) {if (rdev->mode_info.atom_context) {kfree (rdev->mode_info.atom_context->scratch); +kfree (rdev->mode_info.atom_context->iio); }kfree (rdev->mode_info.atom_context); rdev->mode_info.atom_context =NULL ;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 314/529 drm: amd: display: Fix memory leakage
In reply to Greg Kroah-HartmanFrom: Konstantin Meskhidze <[email protected]>
[ Upstream commit 6b8701be1f66064ca72733c5f6e13748cdbf8397 ]
This commit fixes memory leakage in dc_construct_ctx() function.
--- drivers/gpu/drm/amd/display/dc/core/dc.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/amd/display/dc/core/dc.c +1 -0
@@ -616,6 +616,7 @@ static bool dc_construct_ctx(struct dc *dc, dc_ctx->perf_trace =dc_perf_trace_create ();if (!dc_ctx->perf_trace) { +kfree (dc_ctx);ASSERT_CRITICAL (false);return false; }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 315/529 drm/msm/dsi: Add missing check for alloc_ordered_workqueue
In reply to Greg Kroah-HartmanFrom: Jiasheng Jiang <[email protected]>
[ Upstream commit 115906ca7b535afb1fe7b5406c566ccd3873f82b ]
Add check for the return value of alloc_ordered_workqueue as it may return NULL pointer and cause NULL pointer dereference.
Patchwork: https://patchwork.freedesktop.org/patch/517646/
--- drivers/gpu/drm/msm/dsi/dsi_host.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/gpu/drm/msm/dsi/dsi_host.c +3 -0
@@ -1913,6 +1913,9 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi)/* setup workqueue */ msm_host->workqueue =alloc_ordered_workqueue ("dsi_drm_work" ,0 ); +if (!msm_host->workqueue) +return -ENOMEM ; +INIT_WORK (&msm_host->err_work, dsi_err_worker);INIT_WORK (&msm_host->hpd_work, dsi_hpd_worker);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 316/529 docs/scripts/gdb: add necessary make scripts_gdb step
In reply to Greg Kroah-HartmanFrom: Jakob Koschel <[email protected]>
[ Upstream commit 6b219431037bf98c9efd49716aea9b68440477a3 ]
In order to debug the kernel successfully with gdb you need to run 'make scripts_gdb' nowadays.
This was changed with the following commit:
Commit 67274c083438340ad16c ("scripts/gdb: delay generation of gdb constants.py")
In order to have a complete guide for beginners this remark should be added to the offial documentation.
--- Documentation/dev-tools/gdb-kernel-debugging.rst | 4 ++++ 1 file changed, 4 insertions(+)
Documentation/dev-tools/gdb-kernel-debugging.rst +4 -0
@@ -39,6 +39,10 @@ Setup this mode. In this case, you should build the kernel with CONFIG_RANDOMIZE_BASE disabled if the architecture supports KASLR. +- Build the gdb scripts (required on kernels v5.1 and above):: + + make scripts_gdb + - Enable the gdb stub of QEMU/KVM, either - at VM startup time by appending "-s" to the QEMU command line
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 317/529 ASoC: kirkwood: Iterate over array indexes instead of using pointer math
In reply to Greg Kroah-HartmanFrom: Kees Cook <[email protected]>
[ Upstream commit b3bcedc0402fcdc5c8624c433562d9d1882749d8 ]
Walking the dram->cs array was seen as accesses beyond the first array item by the compiler. Instead, use the array index directly. This allows for run-time bounds checking under CONFIG_UBSAN_BOUNDS as well. Seen with GCC 13 with -fstrict-flex-arrays:
../sound/soc/kirkwood/kirkwood-dma.c: In function
'kirkwood_dma_conf_mbus_windows.constprop':../sound/soc/kirkwood/kirkwood-dma.c:90:24: warning: array subscript 0 is outside array bounds of 'const struct mbus_dram_window[0]' [-Warray-bounds=]
90 | if ((cs->base & 0xffff0000) < (dma & 0xffff0000)) {
| ~~^~~~~~--- sound/soc/kirkwood/kirkwood-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/kirkwood/kirkwood-dma.c +1 -1
@@ -86,7 +86,7 @@ kirkwood_dma_conf_mbus_windows(void __iomem *base, int win,/* try to find matching cs for current dma address */ for (i =0 ; i < dram->num_cs; i++) { -const struct mbus_dram_window *cs = dram->cs + i; +const struct mbus_dram_window *cs = &dram->cs[i];if ((cs->base &0xffff0000 ) < (dma &0xffff0000 )) {writel (cs->base &0xffff0000 , base +KIRKWOOD_AUDIO_WIN_BASE_REG (win));
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 318/529 regulator: max77802: Bounds check regulator id against opmode
In reply to Greg Kroah-HartmanFrom: Kees Cook <[email protected]>
[ Upstream commit 4fd8bcec5fd7c0d586206fa2f42bd67b06cdaa7e ]
Explicitly bounds-check the id before accessing the opmode array. Seen with GCC 13:
../drivers/regulator/max77802-regulator.c: In function 'max77802_enable':../drivers/regulator/max77802-regulator.c:217:29: warning: array subscript [0, 41] is outside array bounds of 'unsigned int[42]' [-Warray-bounds=]
217 | if (max77802->opmode[id] == MAX77802_OFF_PWRREQ)
| ~~~~~~~~~~~~~~~~^~~~
../drivers/regulator/max77802-regulator.c:62:22: note: while referencing 'opmode'
62 | unsigned int opmode[MAX77802_REG_MAX];
| ^~~~~~
--- drivers/regulator/max77802-regulator.c | 34 ++++++++++++++++++-------- 1 file changed, 24 insertions(+), 10 deletions(-)
drivers/regulator/max77802-regulator.c +24 -10
@@ -95,9 +95,11 @@ static int max77802_set_suspend_disable(struct regulator_dev *rdev) {unsigned int val =MAX77802_OFF_PWRREQ ;struct max77802_regulator_prv *max77802 =rdev_get_drvdata (rdev); -int id =rdev_get_id (rdev); +unsigned int id =rdev_get_id (rdev);int shift =max77802_get_opmode_shift (id); +if (WARN_ON_ONCE (id >=ARRAY_SIZE (max77802->opmode))) +return -EINVAL ; max77802->opmode[id] = val;return regmap_update_bits (rdev->regmap, rdev->desc->enable_reg, rdev->desc->enable_mask, val << shift);
@@ -111,7 +113,7 @@ static int max77802_set_suspend_disable(struct regulator_dev *rdev)static int max77802_set_mode (struct regulator_dev *rdev,unsigned int mode) {struct max77802_regulator_prv *max77802 =rdev_get_drvdata (rdev); -int id =rdev_get_id (rdev); +unsigned int id =rdev_get_id (rdev);unsigned int val;int shift =max77802_get_opmode_shift (id);
@@ -128,6 +130,9 @@ static int max77802_set_mode(struct regulator_dev *rdev, unsigned int mode)return -EINVAL ; } +if (WARN_ON_ONCE (id >=ARRAY_SIZE (max77802->opmode))) +return -EINVAL ; + max77802->opmode[id] = val;return regmap_update_bits (rdev->regmap, rdev->desc->enable_reg, rdev->desc->enable_mask, val << shift);
@@ -136,8 +141,10 @@ static int max77802_set_mode(struct regulator_dev *rdev, unsigned int mode)static unsigned max77802_get_mode (struct regulator_dev *rdev) {struct max77802_regulator_prv *max77802 =rdev_get_drvdata (rdev); -int id =rdev_get_id (rdev); +unsigned int id =rdev_get_id (rdev); +if (WARN_ON_ONCE (id >=ARRAY_SIZE (max77802->opmode))) +return -EINVAL ;return max77802_map_mode (max77802->opmode[id]); }
@@ -161,10 +168,13 @@ static int max77802_set_suspend_mode(struct regulator_dev *rdev, unsigned int mode) {struct max77802_regulator_prv *max77802 =rdev_get_drvdata (rdev); -int id =rdev_get_id (rdev); +unsigned int id =rdev_get_id (rdev);unsigned int val;int shift =max77802_get_opmode_shift (id); +if (WARN_ON_ONCE (id >=ARRAY_SIZE (max77802->opmode))) +return -EINVAL ; +/* * If the regulator has been disabled for suspend * then is invalid to try setting a suspend mode.
@@ -210,9 +220,11 @@ static int max77802_set_suspend_mode(struct regulator_dev *rdev,static int max77802_enable (struct regulator_dev *rdev) {struct max77802_regulator_prv *max77802 =rdev_get_drvdata (rdev); -int id =rdev_get_id (rdev); +unsigned int id =rdev_get_id (rdev);int shift =max77802_get_opmode_shift (id); +if (WARN_ON_ONCE (id >=ARRAY_SIZE (max77802->opmode))) +return -EINVAL ;if (max77802->opmode[id] ==MAX77802_OFF_PWRREQ ) max77802->opmode[id] =MAX77802_OPMODE_NORMAL ;
@@ -541,7 +553,7 @@ static int max77802_pmic_probe(struct platform_device *pdev)for (i =0 ; i <MAX77802_REG_MAX ; i++) {struct regulator_dev *rdev; -int id = regulators[i].id; +unsigned int id = regulators[i].id;int shift =max77802_get_opmode_shift (id);int ret;
@@ -559,10 +571,12 @@ static int max77802_pmic_probe(struct platform_device *pdev)* the hardware reports OFF as the regulator operating mode. * Default to operating mode NORMAL in that case. */ -if (val ==MAX77802_STATUS_OFF ) - max77802->opmode[id] =MAX77802_OPMODE_NORMAL ; -else - max77802->opmode[id] = val; +if (id <ARRAY_SIZE (max77802->opmode)) { +if (val ==MAX77802_STATUS_OFF ) + max77802->opmode[id] =MAX77802_OPMODE_NORMAL ; +else + max77802->opmode[id] = val; + } rdev =devm_regulator_register (&pdev->dev, ®ulators[i], &config);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 319/529 regulator: s5m8767: Bounds check id indexing into arrays
In reply to Greg Kroah-HartmanFrom: Kees Cook <[email protected]>
[ Upstream commit e314e15a0b58f9d051c00b25951073bcdae61953 ]
The compiler has no way to know if "id" is within the array bounds of the regulators array. Add a check for this and a build-time check that the regulators and reg_voltage_map arrays are sized the same. Seen with GCC 13:
../drivers/regulator/s5m8767.c: In function 's5m8767_pmic_probe':../drivers/regulator/s5m8767.c:936:35: warning: array subscript [0, 36] is outside array bounds of 'struct regulator_desc[37]' [-Warray-bounds=]
936 | regulators[id].vsel_reg =
| ~~~~~~~~~~^~~~--- drivers/regulator/s5m8767.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/regulator/s5m8767.c +5 -1
@@ -923,10 +923,14 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)for (i =0 ; i < pdata->num_regulators; i++) {const struct sec_voltage_desc *desc; -int id = pdata->regulators[i].id; +unsigned int id = pdata->regulators[i].id;int enable_reg, enable_val;struct regulator_dev *rdev; +BUILD_BUG_ON (ARRAY_SIZE (regulators) !=ARRAY_SIZE (reg_voltage_map)); +if (WARN_ON_ONCE (id >=ARRAY_SIZE (regulators))) +continue ; + desc = reg_voltage_map[id];if (desc) { regulators[id].n_voltages =
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 320/529 gfs2: Improve gfs2_make_fs_rw error handling
In reply to Greg Kroah-HartmanFrom: Andreas Gruenbacher <[email protected]>
[ Upstream commit b66f723bb552ad59c2acb5d45ea45c890f84498b ]
In gfs2_make_fs_rw(), make sure to call gfs2_consist() to report an inconsistency and mark the filesystem as withdrawn when gfs2_find_jhead() fails.
At the end of gfs2_make_fs_rw(), when we discover that the filesystem has been withdrawn, make sure we report an error. This also replaces the gfs2_withdrawn() check after gfs2_find_jhead().
--- fs/gfs2/super.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
fs/gfs2/super.c +6 -2
@@ -145,8 +145,10 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp)return -EIO ; error =gfs2_find_jhead (sdp->sd_jdesc, &head, false); -if (error ||gfs2_withdrawn (sdp)) +if (error) { +gfs2_consist (sdp);return error; + }if (!(head.lh_flags &GFS2_LOG_HEAD_UNMOUNT )) {gfs2_consist (sdp);
@@ -158,7 +160,9 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp)gfs2_log_pointers_init (sdp, head.lh_blkno); error =gfs2_quota_init (sdp); -if (!error && !gfs2_withdrawn (sdp)) +if (!error &&gfs2_withdrawn (sdp)) + error = -EIO ; +if (!error)set_bit (SDF_JOURNAL_LIVE , &sdp->sd_flags);return error; }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 321/529 hwmon: (coretemp) Simplify platform device handling
In reply to Greg Kroah-HartmanFrom: Robin Murphy <[email protected]>
[ Upstream commit 6d03bbff456befeccdd4d663177c4d6c75d0c4ff ]
Coretemp's platform driver is unconventional. All the real work is done globally by the initcall and CPU hotplug notifiers, while the "driver" effectively just wraps an allocation and the registration of the hwmon interface in a long-winded round-trip through the driver core. The whole logic of dynamically creating and destroying platform devices to bring the interfaces up and down is error prone, since it assumes platform_device_add() will synchronously bind the driver and set drvdata before it returns, thus results in a NULL dereference if drivers_autoprobe is turned off for the platform bus. Furthermore, the unusual approach of doing that from within a CPU hotplug notifier, already commented in the code that it deadlocks suspend, also causes lockdep issues for other drivers or subsystems which may want to legitimately register a CPU hotplug notifier from a platform bus notifier.
All of these issues can be solved by ripping this unusual behaviour out completely, simply tying the platform devices to the lifetime of the module itself, and directly managing the hwmon interfaces from the hotplug notifiers. There is a slight user-visible change in that /sys/bus/platform/drivers/coretemp will no longer appear, and /sys/devices/platform/coretemp.n will remain present if package n is hotplugged off, but hwmon users should really only be looking for the presence of the hwmon interfaces, whose behaviour remains unchanged.
--- drivers/hwmon/coretemp.c | 128 ++++++++++++++++++--------------------- 1 file changed, 58 insertions(+), 70 deletions(-)
drivers/hwmon/coretemp.c +58 -70
@@ -550,66 +550,49 @@ static void coretemp_remove_core(struct platform_data *pdata, int indx)ida_free (&pdata->ida, indx -BASE_SYSFS_ATTR_NO ); } -static int coretemp_probe (struct platform_device *pdev) +static int coretemp_device_add (int zoneid) { -struct device *dev = &pdev->dev; +struct platform_device *pdev;struct platform_data *pdata; +int err;/* Initialize the per-zone data structures */ - pdata =devm_kzalloc (dev,sizeof (struct platform_data ),GFP_KERNEL ); + pdata =kzalloc (sizeof (*pdata),GFP_KERNEL );if (!pdata)return -ENOMEM ; - pdata->pkg_id = pdev->id; + pdata->pkg_id = zoneid;ida_init (&pdata->ida); -platform_set_drvdata (pdev, pdata); - pdata->hwmon_dev =devm_hwmon_device_register_with_groups (dev,DRVNAME , - pdata,NULL ); -return PTR_ERR_OR_ZERO (pdata->hwmon_dev); -} - -static int coretemp_remove (struct platform_device *pdev) -{ -struct platform_data *pdata =platform_get_drvdata (pdev); -int i; + pdev =platform_device_alloc (DRVNAME , zoneid); +if (!pdev) { + err = -ENOMEM ; + goto err_free_pdata; + } -for (i =MAX_CORE_DATA -1 ; i >=0 ; --i) -if (pdata->core_data[i]) -coretemp_remove_core (pdata, i); + err =platform_device_add (pdev); +if (err) + goto err_put_dev; -ida_destroy (&pdata->ida); +platform_set_drvdata (pdev, pdata); + zone_devices[zoneid] = pdev;return 0 ; -} -static struct platform_driver coretemp_driver = { - .driver = { - .name =DRVNAME , - }, - .probe = coretemp_probe, - .remove = coretemp_remove, -}; +err_put_dev: +platform_device_put (pdev); +err_free_pdata: +kfree (pdata); +return err; +} -static struct platform_device *coretemp_device_add (unsigned int cpu) +static void coretemp_device_remove (int zoneid) { -int err, zoneid =topology_logical_die_id (cpu); -struct platform_device *pdev; - -if (zoneid <0 ) -return ERR_PTR (-ENOMEM ); - - pdev =platform_device_alloc (DRVNAME , zoneid); -if (!pdev) -return ERR_PTR (-ENOMEM ); - - err =platform_device_add (pdev); -if (err) { -platform_device_put (pdev); -return ERR_PTR (err); - } +struct platform_device *pdev = zone_devices[zoneid]; +struct platform_data *pdata =platform_get_drvdata (pdev); - zone_devices[zoneid] = pdev; -return pdev; +ida_destroy (&pdata->ida); +kfree (pdata); +platform_device_unregister (pdev); }static int coretemp_cpu_online (unsigned int cpu)
@@ -633,7 +616,10 @@ static int coretemp_cpu_online(unsigned int cpu)if (!cpu_has (c,X86_FEATURE_DTHERM ))return -ENODEV ; -if (!pdev) { + pdata =platform_get_drvdata (pdev); +if (!pdata->hwmon_dev) { +struct device *hwmon; +/* Check the microcode version of the CPU */ if (chk_ucode_version (cpu))return -EINVAL ;
@@ -644,9 +630,11 @@ static int coretemp_cpu_online(unsigned int cpu)* online. So, initialize per-pkg data structures and * then bring this core online. */ - pdev =coretemp_device_add (cpu); -if (IS_ERR (pdev)) -return PTR_ERR (pdev); + hwmon =hwmon_device_register_with_groups (&pdev->dev,DRVNAME , + pdata,NULL ); +if (IS_ERR (hwmon)) +return PTR_ERR (hwmon); + pdata->hwmon_dev = hwmon;/* * Check whether pkgtemp support is available.
@@ -656,7 +644,6 @@ static int coretemp_cpu_online(unsigned int cpu)coretemp_add_core (pdev, cpu,1 ); } - pdata =platform_get_drvdata (pdev);/* * Check whether a thread sibling is already online. If not add the * interface for this CPU core.
@@ -675,18 +662,14 @@ static int coretemp_cpu_offline(unsigned int cpu)struct temp_data *tdata;int i, indx =-1 , target; -/* -* Don't execute this on suspend as the device remove locks -* up the machine. -*/ +/* No need to tear down any interfaces for suspend */ if (cpuhp_tasks_frozen)return 0 ;/* If the physical CPU device does not exist, just return */ -if (!pdev) -return 0 ; - pd =platform_get_drvdata (pdev); +if (!pd->hwmon_dev) +return 0 ;for (i =0 ; i <NUM_REAL_CORES ; i++) {if (pd->cpu_map[i] ==topology_core_id (cpu)) {
@@ -718,13 +701,14 @@ static int coretemp_cpu_offline(unsigned int cpu) }/* -* If all cores in this pkg are offline, remove the device. This -* will invoke the platform driver remove function, which cleans up -* the rest. +* If all cores in this pkg are offline, remove the interface. */ + tdata = pd->core_data[PKG_SYSFS_ATTR_NO ];if (cpumask_empty (&pd->cpumask)) { - zone_devices[topology_logical_die_id (cpu)] =NULL ; -platform_device_unregister (pdev); +if (tdata) +coretemp_remove_core (pd,PKG_SYSFS_ATTR_NO ); +hwmon_device_unregister (pd->hwmon_dev); + pd->hwmon_dev =NULL ;return 0 ; }
@@ -732,7 +716,6 @@ static int coretemp_cpu_offline(unsigned int cpu)* Check whether this core is the target for the package * interface. We need to assign it to some other cpu. */ - tdata = pd->core_data[PKG_SYSFS_ATTR_NO ];if (tdata && tdata->cpu == cpu) { target =cpumask_first (&pd->cpumask);mutex_lock (&tdata->update_lock);
@@ -751,7 +734,7 @@ static enum cpuhp_state coretemp_hp_online;static int __init coretemp_init (void ) { -int err; +int i, err;/* * CPUID.06H.EAX[0] indicates whether the CPU has thermal
@@ -767,20 +750,22 @@ static int __init coretemp_init(void)if (!zone_devices)return -ENOMEM ; - err =platform_driver_register (&coretemp_driver); -if (err) - goto outzone; +for (i =0 ; i < max_zones; i++) { + err =coretemp_device_add (i); +if (err) + goto outzone; + } err =cpuhp_setup_state (CPUHP_AP_ONLINE_DYN ,"hwmon/coretemp:online" , coretemp_cpu_online, coretemp_cpu_offline);if (err <0 ) - goto outdrv; + goto outzone; coretemp_hp_online = err;return 0 ; -outdrv: -platform_driver_unregister (&coretemp_driver); outzone: +while (i--) +coretemp_device_remove (i);kfree (zone_devices);return err; }
@@ -788,8 +773,11 @@ module_init(coretemp_init) static void __exit coretemp_exit(void) { +int i; +cpuhp_remove_state (coretemp_hp_online); -platform_driver_unregister (&coretemp_driver); +for (i =0 ; i < max_zones; i++) +coretemp_device_remove (i);kfree (zone_devices); }module_exit (coretemp_exit)
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 322/529 pinctrl: at91: use devm_kasprintf() to avoid potential leaks
In reply to Greg Kroah-HartmanFrom: Claudiu Beznea <[email protected]>
[ Upstream commit 1c4e5c470a56f7f7c649c0c70e603abc1eab15c4 ]
Use devm_kasprintf() instead of kasprintf() to avoid any potential leaks. At the moment drivers have no remove functionality thus there is no need for fixes tag.
--- drivers/pinctrl/pinctrl-at91-pio4.c | 4 ++-- drivers/pinctrl/pinctrl-at91.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)
drivers/pinctrl/pinctrl-at91-pio4.c +2 -2
@@ -1081,8 +1081,8 @@ static int atmel_pinctrl_probe(struct platform_device *pdev) pin_desc[i].number = i;/* Pin naming convention: P(bank_name)(bank_pin_number). */ - pin_desc[i].name =kasprintf (GFP_KERNEL ,"P%c%d" , - bank +'A' , line); + pin_desc[i].name =devm_kasprintf (&pdev->dev,GFP_KERNEL ,"P%c%d" , + bank +'A' , line); group->name = group_names[i] = pin_desc[i].name; group->pin = pin_desc[i].number;
drivers/pinctrl/pinctrl-at91.c +1 -1
@@ -1891,7 +1891,7 @@ static int at91_gpio_probe(struct platform_device *pdev) }for (i =0 ; i < chip->ngpio; i++) - names[i] =kasprintf (GFP_KERNEL ,"pio%c%d" , alias_idx +'A' , i); + names[i] =devm_kasprintf (&pdev->dev,GFP_KERNEL ,"pio%c%d" , alias_idx +'A' , i); chip->names = (const char *const *)names;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 323/529 HID: logitech-hidpp: Dont restart communication if not necessary
In reply to Greg Kroah-HartmanFrom: Bastien Nocera <[email protected]>
[ Upstream commit 498ba20690357691103de0f766960355247c78be ]
Don't stop and restart communication with the device unless we need to modify the connect flags used because of a device quirk.
--- drivers/hid/hid-logitech-hidpp.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-)
drivers/hid/hid-logitech-hidpp.c +20 -12
@@ -3763,6 +3763,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)bool connected;unsigned int connect_mask =HID_CONNECT_DEFAULT ;struct hidpp_ff_private_data data; +bool will_restart = false;/* report_fixup needs drvdata to be set before we call hid_parse */ hidpp =devm_kzalloc (&hdev->dev,sizeof (*hidpp),GFP_KERNEL );
@@ -3818,6 +3819,10 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)return ret; } +if (hidpp->quirks &HIDPP_QUIRK_DELAYED_INIT || + hidpp->quirks &HIDPP_QUIRK_UNIFYING ) + will_restart = true; +INIT_WORK (&hidpp->work, delayed_work_cb);mutex_init (&hidpp->send_mutex);init_waitqueue_head (&hidpp->wait);
@@ -3832,7 +3837,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)* Plain USB connections need to actually call start and open * on the transport driver to allow incoming data. */ - ret =hid_hw_start (hdev,0 ); + ret =hid_hw_start (hdev, will_restart ?0 : connect_mask);if (ret) {hid_err (hdev,"hw start failed\n" ); goto hid_hw_start_fail;
@@ -3869,6 +3874,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) hidpp->wireless_feature_index =0 ; else if (ret) goto hid_hw_init_fail; + ret = 0; }if (connected && (hidpp->quirks &HIDPP_QUIRK_CLASS_WTP )) {
@@ -3883,19 +3889,21 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)hidpp_connect_event (hidpp); -/* Reset the HID node state */ -hid_device_io_stop (hdev); -hid_hw_close (hdev); -hid_hw_stop (hdev); +if (will_restart) { +/* Reset the HID node state */ +hid_device_io_stop (hdev); +hid_hw_close (hdev); +hid_hw_stop (hdev); -if (hidpp->quirks &HIDPP_QUIRK_NO_HIDINPUT ) - connect_mask &= ~HID_CONNECT_HIDINPUT ; +if (hidpp->quirks &HIDPP_QUIRK_NO_HIDINPUT ) + connect_mask &= ~HID_CONNECT_HIDINPUT ; -/* Now export the actual inputs and hidraw nodes to the world */ - ret =hid_hw_start (hdev, connect_mask); -if (ret) { -hid_err (hdev,"%s:hid_hw_start returned error\n" , __func__); - goto hid_hw_start_fail; +/* Now export the actual inputs and hidraw nodes to the world */ + ret =hid_hw_start (hdev, connect_mask); +if (ret) { +hid_err (hdev,"%s:hid_hw_start returned error\n" , __func__); + goto hid_hw_start_fail; + } }if (hidpp->quirks &HIDPP_QUIRK_CLASS_G920 ) {
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 324/529 drm: panel-orientation-quirks: Add quirk for Lenovo IdeaPad Duet 3 10IGL5
In reply to Greg Kroah-HartmanFrom: Darrell Kavanagh <[email protected]>
[ Upstream commit 38b2d8efd03d2e56431b611e3523f0158306451d ]
Another Lenovo convertable where the panel is installed landscape but is reported to the kernel as portrait.
--- drivers/gpu/drm/drm_panel_orientation_quirks.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/gpu/drm/drm_panel_orientation_quirks.c +6 -0
@@ -278,6 +278,12 @@ static const struct dmi_system_id orientation_data[] = { DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGL"), }, .driver_data = (void *)&lcd800x1280_rightside_up, + }, { /* Lenovo IdeaPad Duet 3 10IGL5 */ + .matches = { +DMI_EXACT_MATCH (DMI_SYS_VENDOR ,"LENOVO" ), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "IdeaPad Duet 3 10IGL5"), + }, + .driver_data = (void *)&lcd1200x1920_rightside_up, }, { /* Lenovo Yoga Book X90F / X91F / X91L */ .matches = {/* Non exact match to match all versions */
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 325/529 dm thin: add cond_resched() to various workqueue loops
In reply to Greg Kroah-HartmanFrom: Mike Snitzer <[email protected]>
[ Upstream commit e4f80303c2353952e6e980b23914e4214487f2a6 ]
Otherwise on resource constrained systems these workqueues may be too greedy.
--- drivers/md/dm-thin.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/md/dm-thin.c +2 -0
@@ -2217,6 +2217,7 @@ static void process_thin_deferred_bios(struct thin_c *tc)throttle_work_update (&pool->throttle);dm_pool_issue_prefetches (pool->pmd); } +cond_resched (); }blk_finish_plug (&plug); }
@@ -2299,6 +2300,7 @@ static void process_thin_deferred_cells(struct thin_c *tc)else pool->process_cell (tc, cell); } +cond_resched (); }while (!list_empty (&cells)); }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 326/529 dm cache: add cond_resched() to various workqueue loops
In reply to Greg Kroah-HartmanFrom: Mike Snitzer <[email protected]>
[ Upstream commit 76227f6dc805e9e960128bcc6276647361e0827c ]
Otherwise on resource constrained systems these workqueues may be too greedy.
--- drivers/md/dm-cache-target.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/md/dm-cache-target.c +4 -0
@@ -1883,6 +1883,7 @@ static void process_deferred_bios(struct work_struct *ws)else commit_needed =process_bio (cache, bio) || commit_needed; +cond_resched (); }if (commit_needed)
@@ -1905,6 +1906,7 @@ static void requeue_deferred_bios(struct cache *cache)while ((bio =bio_list_pop (&bios))) { bio->bi_status =BLK_STS_DM_REQUEUE ;bio_endio (bio); +cond_resched (); } }
@@ -1945,6 +1947,8 @@ static void check_migrations(struct work_struct *ws) r =mg_start (cache, op,NULL );if (r)break ; + +cond_resched (); } }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 327/529 nfsd: zero out pointers after putting nfsd_files on COPY setup error
In reply to Greg Kroah-HartmanFrom: Jeff Layton <[email protected]>
[ Upstream commit 1f0001d43d0c0ac2a19a34a914f6595ad97cbc1d ]
At first, I thought this might be a source of nfsd_file overputs, but the current callers seem to avoid an extra put when nfsd4_verify_copy returns an error.
Still, it's "bad form" to leave the pointers filled out when we don't have a reference to them anymore, and that might lead to bugs later. Zero them out as a defensive coding measure.
--- fs/nfsd/nfs4proc.c | 2 ++ 1 file changed, 2 insertions(+)
fs/nfsd/nfs4proc.c +2 -0
@@ -1075,8 +1075,10 @@ nfsd4_verify_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,return status; out_put_dst:nfsd_file_put (*dst); + *dst =NULL ; out_put_src:nfsd_file_put (*src); + *src =NULL ; goto out; }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 328/529 wifi: rtl8xxxu: fixing transmisison failure for rtl8192eu
In reply to Greg Kroah-HartmanFrom: Jun ASAKA <[email protected]>
commit c6015bf3ff1ffb3caa27eb913797438a0fc634a0 upstream.
Fixing transmission failure which results in "authentication with ... timed out". This can be fixed by disable the REG_TXPAUSE.
--- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c +5 -0
@@ -1671,6 +1671,11 @@ static void rtl8192e_enable_rf(struct rt val8 =rtl8xxxu_read8 (priv,REG_PAD_CTRL1 ); val8 &= ~BIT (0 );rtl8xxxu_write8 (priv,REG_PAD_CTRL1 , val8); + +/* +* Fix transmission failure of rtl8192e. +*/ +rtl8xxxu_write8 (priv,REG_TXPAUSE ,0x00 ); }struct rtl8xxxu_fileops rtl8192eu_fops = {
Greg Kroah-Hartman
maintainerPATCH 329/529 firmware: coreboot: framebuffer: Ignore reserved pixel color bits
In reply to Greg Kroah-HartmanFrom: Alper Nebi Yasak <[email protected]>
commit e6acaf25cba14661211bb72181c35dd13b24f5b3 upstream.
The coreboot framebuffer doesn't support transparency, its 'reserved' bit field is merely padding for byte/word alignment of pixel colors [1]. When trying to match the framebuffer to a simplefb format, the kernel driver unnecessarily requires the format's transparency bit field to exactly match this padding, even if the former is zero-width.
Due to a coreboot bug [2] (fixed upstream), some boards misreport the reserved field's size as equal to its position (0x18 for both on a 'Lick' Chromebook), and the driver fails to probe where it would have otherwise worked fine with e.g. the a8r8g8b8 or x8r8g8b8 formats.
Remove the transparency comparison with reserved bits. When the bits-per-pixel and other color components match, transparency will already be in a subset of the reserved field. Not forcing it to match reserved bits allows the driver to work on the boards which misreport the reserved field. It also enables using simplefb formats that don't have transparency bits, although this doesn't currently happen due to format support and ordering in linux/platform_data/simplefb.h.
[1] https://review.coreboot.org/plugins/gitiles/coreboot/+/4.19/src/commonlib/include/commonlib/coreboot_tables.h#255
[2] https://review.coreboot.org/plugins/gitiles/coreboot/+/4.13/src/drivers/intel/fsp2_0/graphics.c#82
--- drivers/firmware/google/framebuffer-coreboot.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
drivers/firmware/google/framebuffer-coreboot.c +1 -3
@@ -43,9 +43,7 @@ static int framebuffer_probe(struct core fb->green_mask_pos == formats[i].green.offset && fb->green_mask_size == formats[i].green.length && fb->blue_mask_pos == formats[i].blue.offset && - fb->blue_mask_size == formats[i].blue.length && - fb->reserved_mask_pos == formats[i].transp.offset && - fb->reserved_mask_size == formats[i].transp.length) + fb->blue_mask_size == formats[i].blue.length) pdata.format = formats[i].name; }if (!pdata.format)
Greg Kroah-Hartman
maintainerPATCH 330/529 rtc: pm8xxx: fix set-alarm race
In reply to Greg Kroah-HartmanFrom: Johan Hovold <[email protected]>
commit c88db0eff9722fc2b6c4d172a50471d20e08ecc6 upstream.
Make sure to disable the alarm before updating the four alarm time registers to avoid spurious alarms during the update.
Note that the disable needs to be done outside of the ctrl_reg_lock section to prevent a racing alarm interrupt from disabling the newly set alarm when the lock is released.
--- drivers/rtc/rtc-pm8xxx.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-)
drivers/rtc/rtc-pm8xxx.c +10 -14
@@ -219,7 +219,6 @@ static int pm8xxx_rtc_set_alarm(struct d {int rc, i;u8 value[NUM_8_BIT_RTC_REGS ]; -unsigned int ctrl_reg;unsigned long secs, irq_flags;struct pm8xxx_rtc *rtc_dd =dev_get_drvdata (dev);const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;
@@ -231,6 +230,11 @@ static int pm8xxx_rtc_set_alarm(struct d secs >>=8 ; } + rc =regmap_update_bits (rtc_dd->regmap, regs->alarm_ctrl, + regs->alarm_en,0 ); +if (rc) +return rc; +spin_lock_irqsave (&rtc_dd->ctrl_reg_lock, irq_flags); rc = regmap_bulk_write(rtc_dd->regmap, regs->alarm_rw, value,
@@ -240,19 +244,11 @@ static int pm8xxx_rtc_set_alarm(struct d goto rtc_rw_fail; } - rc =regmap_read (rtc_dd->regmap, regs->alarm_ctrl, &ctrl_reg); -if (rc) - goto rtc_rw_fail; - -if (alarm->enabled) - ctrl_reg |= regs->alarm_en; -else - ctrl_reg &= ~regs->alarm_en; - - rc =regmap_write (rtc_dd->regmap, regs->alarm_ctrl, ctrl_reg); -if (rc) { -dev_err (dev,"Write to RTC alarm control register failed\n" ); - goto rtc_rw_fail; +if (alarm->enabled) { + rc =regmap_update_bits (rtc_dd->regmap, regs->alarm_ctrl, + regs->alarm_en, regs->alarm_en); +if (rc) + goto rtc_rw_fail; } dev_dbg(dev, "Alarm Set for h:m:s=%ptRt, y-m-d=%ptRdr\n",
Greg Kroah-Hartman
maintainerPATCH 331/529 ipmi_ssif: Rename idle state and check
In reply to Greg Kroah-HartmanFrom: Corey Minyard <[email protected]>
commit 8230831c43a328c2be6d28c65d3f77e14c59986b upstream.
Rename the SSIF_IDLE() to IS_SSIF_IDLE(), since that is more clear, and rename SSIF_NORMAL to SSIF_IDLE, since that's more accurate.
--- drivers/char/ipmi/ipmi_ssif.c | 46 +++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 23 deletions(-)
drivers/char/ipmi/ipmi_ssif.c +23 -23
@@ -92,7 +92,7 @@#define SSIF_WATCH_WATCHDOG_TIMEOUT msecs_to_jiffies(250)enum ssif_intf_state { -SSIF_NORMAL , +SSIF_IDLE ,SSIF_GETTING_FLAGS ,SSIF_GETTING_EVENTS ,SSIF_CLEARING_FLAGS ,
@@ -100,8 +100,8 @@ enum ssif_intf_state {/* FIXME - add watchdog stuff. */ }; -#define SSIF_IDLE (ssif) ((ssif)->ssif_state == SSIF_NORMAL \ - && (ssif)->curr_msg == NULL) +#define IS_SSIF_IDLE (ssif) ((ssif)->ssif_state == SSIF_IDLE \ + && (ssif)->curr_msg == NULL)/* * Indexes into stats[] in ssif_info below.
@@ -348,9 +348,9 @@ static void return_hosed_msg(struct ssif/* * Must be called with the message lock held. This will release the -* message lock. Note that the caller will check SSIF_IDLE and start a -* new operation, so there is no need to check for new messages to -* start in here. +* message lock. Note that the caller will check IS_SSIF_IDLE and +* start a new operation, so there is no need to check for new +* messages to start in here. */ static void start_clear_flags (struct ssif_info *ssif_info,unsigned long *flags) {
@@ -367,7 +367,7 @@ static void start_clear_flags(struct ssiif (start_send (ssif_info, msg,3 ) !=0 ) {/* Error, just go to normal state. */ - ssif_info->ssif_state =SSIF_NORMAL ; + ssif_info->ssif_state =SSIF_IDLE ; } }
@@ -382,7 +382,7 @@ static void start_flag_fetch(struct ssif mb[0 ] = (IPMI_NETFN_APP_REQUEST <<2 ); mb[1 ] =IPMI_GET_MSG_FLAGS_CMD ;if (start_send (ssif_info, mb,2 ) !=0 ) - ssif_info->ssif_state =SSIF_NORMAL ; + ssif_info->ssif_state =SSIF_IDLE ; } static void check_start_send(struct ssif_info *ssif_info, unsigned long *flags,
@@ -393,7 +393,7 @@ static void check_start_send(struct ssif flags =ipmi_ssif_lock_cond (ssif_info, &oflags); ssif_info->curr_msg =NULL ; - ssif_info->ssif_state =SSIF_NORMAL ; + ssif_info->ssif_state =SSIF_IDLE ;ipmi_ssif_unlock_cond (ssif_info, flags);ipmi_free_smi_msg (msg); }
@@ -407,7 +407,7 @@ static void start_event_fetch(struct ssi msg =ipmi_alloc_smi_msg ();if (!msg) { - ssif_info->ssif_state =SSIF_NORMAL ; + ssif_info->ssif_state =SSIF_IDLE ;ipmi_ssif_unlock_cond (ssif_info, flags);return ; }
@@ -430,7 +430,7 @@ static void start_recv_msg_fetch(struct msg =ipmi_alloc_smi_msg ();if (!msg) { - ssif_info->ssif_state =SSIF_NORMAL ; + ssif_info->ssif_state =SSIF_IDLE ;ipmi_ssif_unlock_cond (ssif_info, flags);return ; }
@@ -448,9 +448,9 @@ static void start_recv_msg_fetch(struct/* * Must be called with the message lock held. This will release the -* message lock. Note that the caller will check SSIF_IDLE and start a -* new operation, so there is no need to check for new messages to -* start in here. +* message lock. Note that the caller will check IS_SSIF_IDLE and +* start a new operation, so there is no need to check for new +* messages to start in here. */ static void handle_flags (struct ssif_info *ssif_info,unsigned long *flags) {
@@ -466,7 +466,7 @@ static void handle_flags(struct ssif_inf/* Events available. */ start_event_fetch (ssif_info, flags); else { - ssif_info->ssif_state =SSIF_NORMAL ; + ssif_info->ssif_state =SSIF_IDLE ;ipmi_ssif_unlock_cond (ssif_info, flags); } }
@@ -579,7 +579,7 @@ static void watch_timeout(struct timer_lif (ssif_info->watch_timeout) {mod_timer (&ssif_info->watch_timer, jiffies + ssif_info->watch_timeout); -if (SSIF_IDLE (ssif_info)) { +if (IS_SSIF_IDLE (ssif_info)) {start_flag_fetch (ssif_info, flags);/* Releases lock */ return ; }
@@ -782,7 +782,7 @@ static void msg_done_handler(struct ssif }switch (ssif_info->ssif_state) { -case SSIF_NORMAL : +case SSIF_IDLE :ipmi_ssif_unlock_cond (ssif_info, flags);if (!msg)break ;
@@ -800,7 +800,7 @@ static void msg_done_handler(struct ssif* Error fetching flags, or invalid length, * just give up for now. */ - ssif_info->ssif_state =SSIF_NORMAL ; + ssif_info->ssif_state =SSIF_IDLE ;ipmi_ssif_unlock_cond (ssif_info, flags); dev_warn(&ssif_info->client->dev, "Error getting flags: %d %d, %x\n",
@@ -835,7 +835,7 @@ static void msg_done_handler(struct ssif"Invalid response clearing flags: %x %x\n" , data[0], data[1]); } - ssif_info->ssif_state =SSIF_NORMAL ; + ssif_info->ssif_state =SSIF_IDLE ;ipmi_ssif_unlock_cond (ssif_info, flags);break ;
@@ -913,7 +913,7 @@ static void msg_done_handler(struct ssif } flags =ipmi_ssif_lock_cond (ssif_info, &oflags); -if (SSIF_IDLE (ssif_info) && !ssif_info->stopping) { +if (IS_SSIF_IDLE (ssif_info) && !ssif_info->stopping) {if (ssif_info->req_events)start_event_fetch (ssif_info, flags);else if (ssif_info->req_flags)
@@ -1087,7 +1087,7 @@ static void start_next_msg(struct ssif_iunsigned long oflags; restart: -if (!SSIF_IDLE (ssif_info)) { +if (!IS_SSIF_IDLE (ssif_info)) {ipmi_ssif_unlock_cond (ssif_info, flags);return ; }
@@ -1310,7 +1310,7 @@ static void shutdown_ssif(void *send_infdev_set_drvdata (&ssif_info->client->dev,NULL );/* make sure the driver is not looking for flags any more. */ -while (ssif_info->ssif_state !=SSIF_NORMAL ) +while (ssif_info->ssif_state !=SSIF_IDLE )schedule_timeout (1 ); ssif_info->stopping = true;
@@ -1882,7 +1882,7 @@ static int ssif_probe(struct i2c_client }spin_lock_init (&ssif_info->lock); - ssif_info->ssif_state =SSIF_NORMAL ; + ssif_info->ssif_state =SSIF_IDLE ;timer_setup (&ssif_info->retry_timer, retry_timeout,0 );timer_setup (&ssif_info->watch_timer, watch_timeout,0 );
Greg Kroah-Hartman
maintainerPATCH 332/529 s390/extmem: return correct segment type in __segment_load()
In reply to Greg Kroah-HartmanFrom: Gerald Schaefer <[email protected]>
commit 8c42dd78df148c90e48efff204cce38743906a79 upstream.
Commit f05f62d04271f ("s390/vmem: get rid of memory segment list") reshuffled the call to vmem_add_mapping() in __segment_load(), which now overwrites rc after it was set to contain the segment type code.
As result, __segment_load() will now always return 0 on success, which corresponds to the segment type code SEG_TYPE_SW, i.e. a writeable segment. This results in a kernel crash when loading a read-only segment as dcssblk block device, and trying to write to it.
Instead of reshuffling code again, make sure to return the segment type on success, and also describe this rather delicate and unexpected logic in the function comment. Also initialize new segtype variable with invalid value, to prevent possible future confusion.
--- arch/s390/mm/extmem.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
arch/s390/mm/extmem.c +7 -5
@@ -289,15 +289,17 @@ segment_overlaps_others (struct dcss_seg/* * real segment loading function, called from segment_load +* Must return either an error code < 0, or the segment type code >= 0 */ static int __segment_load (char *name,int do_nonshared,unsigned long *addr,unsigned long *end) {unsigned long start_addr, end_addr, dummy;struct dcss_segment *seg; -int rc, diag_cc; +int rc, diag_cc, segtype; start_addr = end_addr =0 ; + segtype =-1 ; seg =kmalloc (sizeof (*seg),GFP_KERNEL |GFP_DMA );if (seg ==NULL ) { rc = -ENOMEM ;
@@ -326,9 +328,9 @@ __segment_load (char *name, int do_nonsh seg->res_name[8 ] ='\0' ;strlcat (seg->res_name," (DCSS)" ,sizeof (seg->res_name)); seg->res->name = seg->res_name; - rc = seg->vm_segtype; -if (rc ==SEG_TYPE_SC || - ((rc ==SEG_TYPE_SR || rc ==SEG_TYPE_ER ) && !do_nonshared)) + segtype = seg->vm_segtype; +if (segtype ==SEG_TYPE_SC || + ((segtype ==SEG_TYPE_SR || segtype ==SEG_TYPE_ER ) && !do_nonshared)) seg->res->flags |=IORESOURCE_READONLY ;/* Check for overlapping resources before adding the mapping. */
@@ -386,7 +388,7 @@ __segment_load (char *name, int do_nonsh out_free:kfree (seg); out: -return rc; +return rc <0 ? rc : segtype; }/*
Greg Kroah-Hartman
maintainerPATCH 333/529 s390: discard .interp section
In reply to Greg Kroah-HartmanFrom: Ilya Leoshkevich <[email protected]>
commit e9c9cb90e76ffaabcc7ca8f275d9e82195fd6367 upstream.
When debugging vmlinux with QEMU + GDB, the following GDB error may occur:
(gdb) c
Continuing.
Warning:
Cannot insert breakpoint -1.
Cannot access memory at address 0xffffffffffff95c0
Command aborted.
(gdb)The reason is that, when .interp section is present, GDB tries to locate the file specified in it in memory and put a number of breakpoints there (see enable_break() function in gdb/solib-svr4.c). Sometimes GDB finds a bogus location that matches its heuristics, fails to set a breakpoint and stops. This makes further debugging impossible.
The .interp section contains misleading information anyway (vmlinux does not need ld.so), so fix by discarding it.
--- arch/s390/kernel/vmlinux.lds.S | 1 + 1 file changed, 1 insertion(+)
arch/s390/kernel/vmlinux.lds.S +1 -0
@@ -188,5 +188,6 @@ SECTIONS DISCARDS /DISCARD/ : { *(.eh_frame) + *(.interp) } }
Greg Kroah-Hartman
maintainerPATCH 334/529 s390/kprobes: fix irq mask clobbering on kprobe reenter from post_handler
In reply to Greg Kroah-HartmanFrom: Vasily Gorbik <[email protected]>
commit 42e19e6f04984088b6f9f0507c4c89a8152d9730 upstream.
Recent test_kprobe_missed kprobes kunit test uncovers the following error (reported when CONFIG_DEBUG_ATOMIC_SLEEP is enabled):
BUG: sleeping function called from invalid context at kernel/locking/mutex.c:580
in_atomic(): 0, irqs_disabled(): 1, non_block: 0, pid: 662, name: kunit_try_catchpreempt_count: 0, expected: 0
RCU nest depth: 0, expected: 0
no locks held by kunit_try_catch/662.
irq event stamp: 280 hardirqs last enabled at (279): [<00000003e60a3d42>] __do_pgm_check+0x17a/0x1c0 hardirqs last disabled at (280): [<00000003e3bd774a>] kprobe_exceptions_notify+0x27a/0x318 softirqs last enabled at (0): [<00000003e3c5c890>] copy_process+0x14a8/0x4c80 softirqs last disabled at (0): [<0000000000000000>] 0x0 CPU: 46 PID: 662 Comm: kunit_try_catch Tainted: G N 6.2.0-173644-g44c18d77f0c0 #2 Hardware name: IBM 3931 A01 704 (LPAR) Call Trace: [<00000003e60a3a00>] dump_stack_lvl+0x120/0x198 [<00000003e3d02e82>] __might_resched+0x60a/0x668 [<00000003e60b9908>] __mutex_lock+0xc0/0x14e0 [<00000003e60bad5a>] mutex_lock_nested+0x32/0x40 [<00000003e3f7b460>] unregister_kprobe+0x30/0xd8 [<00000003e51b2602>] test_kprobe_missed+0xf2/0x268 [<00000003e51b5406>] kunit_try_run_case+0x10e/0x290 [<00000003e51b7dfa>] kunit_generic_run_threadfn_adapter+0x62/0xb8 [<00000003e3ce30f8>] kthread+0x2d0/0x398 [<00000003e3b96afa>] __ret_from_fork+0x8a/0xe8 [<00000003e60ccada>] ret_from_fork+0xa/0x40
The reason for this error report is that kprobes handling code failed to restore irqs.
The problem is that when kprobe is triggered from another kprobe post_handler current sequence of enable_singlestep / disable_singlestep is the following:enable_singlestep <- original kprobe (saves kprobe_saved_imask) enable_singlestep <- kprobe triggered from post_handler (clobbers kprobe_saved_imask) disable_singlestep <- kprobe triggered from post_handler (restores kprobe_saved_imask) disable_singlestep <- original kprobe (restores wrong clobbered kprobe_saved_imask)
There is just one kprobe_ctlblk per cpu and both calls saves and loads irq mask to kprobe_saved_imask. To fix the problem simply move resume_execution (which calls disable_singlestep) before calling post_handler. This also fixes the problem that post_handler is called with pt_regs which were not yet adjusted after single-stepping.
--- arch/s390/kernel/kprobes.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
arch/s390/kernel/kprobes.c +1 -2
@@ -402,12 +402,11 @@ static int post_kprobe_handler(struct ptif (!p)return 0 ; +resume_execution (p, regs);if (kcb->kprobe_status !=KPROBE_REENTER && p->post_handler) { kcb->kprobe_status =KPROBE_HIT_SSDONE ; p->post_handler (p, regs,0 ); } - -resume_execution (p, regs);pop_kprobe (kcb);preempt_enable_no_resched ();
Greg Kroah-Hartman
maintainerPATCH 335/529 s390/kprobes: fix current_kprobe never cleared after kprobes reenter
In reply to Greg Kroah-HartmanFrom: Vasily Gorbik <[email protected]>
commit cd57953936f2213dfaccce10d20f396956222c7d upstream.
Recent test_kprobe_missed kprobes kunit test uncovers the following problem. Once kprobe is triggered from another kprobe (kprobe reenter), all future kprobes on this cpu are considered as kprobe reenter, thus pre_handler and post_handler are not being called and kprobes are counted as "missed".
Commit b9599798f953 ("[S390] kprobes: activation and deactivation") introduced a simpler scheme for kprobes (de)activation and status tracking by using push_kprobe/pop_kprobe, which supposed to work for both initial kprobe entry as well as kprobe reentry and helps to avoid handling those two cases differently. The problem is that a sequence of calls in case of kprobes reenter:push_kprobe() <- NULL (current_kprobe)push_kprobe() <- kprobe1 (current_kprobe)pop_kprobe() -> kprobe1 (current_kprobe)pop_kprobe() -> kprobe1 (current_kprobe)
leaves "kprobe1" as "current_kprobe" on this cpu, instead of setting it to NULL. In fact push_kprobe/pop_kprobe can only store a single state (there is just one prev_kprobe in kprobe_ctlblk). Which is a hack but sufficient, there is no need to have another prev_kprobe just to store NULL. To make a simple and backportable fix simply reset "prev_kprobe" when kprobe is poped from this "stack". No need to worry about "kprobe_status" in this case, because its value is only checked when current_kprobe != NULL.
--- arch/s390/kernel/kprobes.c | 1 + 1 file changed, 1 insertion(+)
arch/s390/kernel/kprobes.c +1 -0
@@ -241,6 +241,7 @@ static void pop_kprobe(struct kprobe_ctl {__this_cpu_write (current_kprobe, kcb->prev_kprobe.kp); kcb->kprobe_status = kcb->prev_kprobe.status; + kcb->prev_kprobe.kp =NULL ; }NOKPROBE_SYMBOL (pop_kprobe);
Greg Kroah-Hartman
maintainerPATCH 336/529 cifs: Fix uninitialized memory read in smb3_qfs_tcon()
In reply to Greg Kroah-HartmanFrom: Volker Lendecke <[email protected]>
commit d447e794a37288ec7a080aa1b044a8d9deebbab7 upstream.
oparms was not fully initialized
--- fs/cifs/smb2ops.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
fs/cifs/smb2ops.c +7 -6
@@ -859,12 +859,13 @@ smb3_qfs_tcon(const unsigned int xid, stbool no_cached_open = tcon->nohandlecache;struct cached_fid *cfid =NULL ; - oparms.tcon = tcon; - oparms.desired_access =FILE_READ_ATTRIBUTES ; - oparms.disposition =FILE_OPEN ; - oparms.create_options =cifs_create_options (cifs_sb,0 ); - oparms.fid = &fid; - oparms.reconnect = false; + oparms = (struct cifs_open_parms ) { + .tcon = tcon, + .desired_access =FILE_READ_ATTRIBUTES , + .disposition =FILE_OPEN , + .create_options =cifs_create_options (cifs_sb,0 ), + .fid = &fid, + };if (no_cached_open) { rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL,
Greg Kroah-Hartman
maintainerPATCH 337/529 ARM: dts: exynos: correct HDMI phy compatible in Exynos4
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
commit af1c89ddb74f170eccd5a57001d7317560b638ea upstream.
The HDMI phy compatible was missing vendor prefix.
--- arch/arm/boot/dts/exynos4.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/boot/dts/exynos4.dtsi +1 -1
@@ -605,7 +605,7 @@ status = "disabled"; hdmi_i2c_phy: hdmiphy@38 { - compatible = "exynos4210-hdmiphy"; + compatible = "samsung,exynos4210-hdmiphy"; reg = <0x38>; }; };
Greg Kroah-Hartman
maintainerPATCH 338/529 hfs: fix missing hfs_bnode_get() in __hfs_bnode_create
In reply to Greg Kroah-HartmanFrom: Liu Shixin <[email protected]>
commit a9dc087fd3c484fd1ed18c5efb290efaaf44ce03 upstream.
Syzbot found a kernel BUG in hfs_bnode_put():
kernel BUG at fs/hfs/bnode.c:466!
invalid opcode: 0000 [#1] PREEMPT SMP KASAN
CPU: 0 PID: 3634 Comm: kworker/u4:5 Not tainted 6.1.0-rc7-syzkaller-00190-g97ee9d1c1696 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022 Workqueue: writeback wb_workfn (flush-7:0) RIP: 0010:hfs_bnode_put+0x46f/0x480 fs/hfs/bnode.c:466 Code: 8a 80 ff e9 73 fe ff ff 89 d9 80 e1 07 80 c1 03 38 c1 0f 8c a0 fe ff ff 48 89 df e8 db 8a 80 ff e9 93 fe ff ff e8 a1 68 2c ff <0f> 0b e8 9a 68 2c ff 0f 0b 0f 1f 84 00 00 00 00 00 55 41 57 41 56 RSP: 0018:ffffc90003b4f258 EFLAGS: 00010293 RAX: ffffffff825e318f RBX: 0000000000000000 RCX: ffff8880739dd7c0 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000 RBP: ffffc90003b4f430 R08: ffffffff825e2d9b R09: ffffed10045157d1 R10: ffffed10045157d1 R11: 1ffff110045157d0 R12: ffff8880228abe80 R13: ffff88807016c000 R14: dffffc0000000000 R15: ffff8880228abe00 FS: 0000000000000000(0000) GS:ffff8880b9800000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fa6ebe88718 CR3: 000000001e93d000 CR4: 00000000003506f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: <TASK> hfs_write_inode+0x1bc/0xb40 write_inode fs/fs-writeback.c:1440 [inline] __writeback_single_inode+0x4d6/0x670 fs/fs-writeback.c:1652 writeback_sb_inodes+0xb3b/0x18f0 fs/fs-writeback.c:1878 __writeback_inodes_wb+0x125/0x420 fs/fs-writeback.c:1949 wb_writeback+0x440/0x7b0 fs/fs-writeback.c:2054 wb_check_start_all fs/fs-writeback.c:2176 [inline] wb_do_writeback fs/fs-writeback.c:2202 [inline] wb_workfn+0x827/0xef0 fs/fs-writeback.c:2235 process_one_work+0x877/0xdb0 kernel/workqueue.c:2289 worker_thread+0xb14/0x1330 kernel/workqueue.c:2436 kthread+0x266/0x300 kernel/kthread.c:376 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:306 </TASK>
The BUG_ON() is triggered at here:
/* Dispose of resources used by a node */
void hfs_bnode_put(struct hfs_bnode *node)
{
if (node) { <skipped>
BUG_ON(!atomic_read(&node->refcnt)); <- we have issue here!!!! <skipped>
}
}
By tracing the refcnt, I found the node is created by hfs_bmap_alloc() with refcnt 1. Then the node is used by hfs_btree_write(). There is a missing of hfs_bnode_get() after find the node. The issue happened in following path:
<alloc>
hfs_bmap_alloc
hfs_bnode_find
__hfs_bnode_create <- allocate a new node with refcnt 1.
hfs_bnode_put <- decrease the refcnt
<write>
hfs_btree_write
hfs_bnode_find
__hfs_bnode_create
hfs_bnode_findhash <- find the node without refcnt increased.
hfs_bnode_put <- trigger the BUG_ON() since refcnt is 0.
--- fs/hfs/bnode.c | 1 + 1 file changed, 1 insertion(+)
fs/hfs/bnode.c +1 -0
@@ -281,6 +281,7 @@ static struct hfs_bnode *__hfs_bnode_cre tree->node_hash[hash] = node; tree->node_hash_cnt++; }else { +hfs_bnode_get (node2);spin_unlock (&tree->hash_lock);kfree (node);wait_event (node2->lock_wq, !test_bit (HFS_BNODE_NEW , &node2->flags));
Greg Kroah-Hartman
maintainerPATCH 339/529 fs: hfsplus: fix UAF issue in hfsplus_put_super
In reply to Greg Kroah-HartmanFrom: Dongliang Mu <[email protected]>
commit 07db5e247ab5858439b14dd7cc1fe538b9efcf32 upstream.
The current hfsplus_put_super first calls hfs_btree_close on sbi->ext_tree, then invokes iput on sbi->hidden_dir, resulting in an use-after-free issue in hfsplus_release_folio.
As shown in hfsplus_fill_super, the error handling code also calls iput before hfs_btree_close.
To fix this error, we move all iput calls before hfsplus_btree_close.
Note that this patch is tested on Syzbot.
--- fs/hfsplus/super.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/hfsplus/super.c +2 -2
@@ -295,11 +295,11 @@ static void hfsplus_put_super(struct suphfsplus_sync_fs (sb,1 ); } +iput (sbi->alloc_file); +iput (sbi->hidden_dir);hfs_btree_close (sbi->attr_tree);hfs_btree_close (sbi->cat_tree);hfs_btree_close (sbi->ext_tree); -iput (sbi->alloc_file); -iput (sbi->hidden_dir);kfree (sbi->s_vhdr_buf);kfree (sbi->s_backup_vhdr_buf);unload_nls (sbi->nls);
Greg Kroah-Hartman
maintainerPATCH 340/529 exfat: fix reporting fs error when reading dir beyond EOF
In reply to Greg Kroah-HartmanFrom: Yuezhang Mo <[email protected]>
commit 706fdcac002316893434d753be8cfb549fe1d40d upstream.
Since seekdir() does not check whether the position is valid, the position may exceed the size of the directory. We found that for a directory with discontinuous clusters, if the position exceeds the size of the directory and the excess size is greater than or equal to the cluster size, exfat_readdir() will return -EIO, causing a file system error and making the file system unavailable.
Reproduce this bug by:
seekdir(dir, dir_size + cluster_size);
dirent = readdir(dir);
The following log will be printed if mount with 'errors=remount-ro'.
[11166.712896] exFAT-fs (sdb1): error, invalid access to FAT (entry 0xffffffff) [11166.712905] exFAT-fs (sdb1): Filesystem has been set read-only
--- fs/exfat/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/exfat/dir.c +1 -1
@@ -102,7 +102,7 @@ static int exfat_readdir(struct inode *i clu.dir = ei->hint_bmap.clu; } -while (clu_offset >0 ) { +while (clu_offset >0 && clu.dir !=EXFAT_EOF_CLUSTER ) {if (exfat_get_next_cluster (sb, &(clu.dir)))return -EIO ;
Greg Kroah-Hartman
maintainerPATCH 341/529 exfat: fix unexpected EOF while reading dir
In reply to Greg Kroah-HartmanFrom: Yuezhang Mo <[email protected]>
commit 6cb5d1a16a51d080fbc1649a5144cbc5ca7d6f88 upstream.
If the position is not aligned with the dentry size, the return value of readdir() will be NULL and errno is 0, which means the end of the directory stream is reached.
If the position is aligned with dentry size, but there is no file or directory at the position, exfat_readdir() will continue to get dentry from the next dentry. So the dentry gotten by readdir() may not be at the position.
After this commit, if the position is not aligned with the dentry size, round the position up to the dentry size and continue to get the dentry.
--- fs/exfat/dir.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
fs/exfat/dir.c +1 -4
@@ -236,10 +236,7 @@ static int exfat_iterate(struct file *fi fake_offset =1 ; } -if (cpos & (DENTRY_SIZE -1 )) { - err = -ENOENT ; - goto unlock; - } + cpos =round_up (cpos,DENTRY_SIZE );/* name buffer should be allocated before use */ err =exfat_alloc_namebuf (nb);
Greg Kroah-Hartman
maintainerPATCH 342/529 exfat: redefine DIR_DELETED as the bad cluster number
In reply to Greg Kroah-HartmanFrom: Sungjong Seo <[email protected]>
commit bdaadfd343e3cba49ad0b009ff4b148dad0fa404 upstream.
When a file or a directory is deleted, the hint for the cluster of its parent directory in its in-memory inode is set as DIR_DELETED. Therefore, DIR_DELETED must be one of invalid cluster numbers. According to the exFAT specification, a volume can have at most 2^32-11 clusters. However, DIR_DELETED is wrongly defined as 0xFFFF0321, which could be a valid cluster number. To fix it, let's redefine DIR_DELETED as 0xFFFFFFF7, the bad cluster number.
--- fs/exfat/exfat_fs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/exfat/exfat_fs.h +1 -1
@@ -42,7 +42,7 @@ enum {#define ES_2_ENTRIES 2#define ES_ALL_ENTRIES 0 -#define DIR_DELETED 0xFFFF0321 +#define DIR_DELETED 0xFFFFFFF7/* type values */ #define TYPE_UNUSED 0x0000
Greg Kroah-Hartman
maintainerPATCH 343/529 exfat: fix inode->i_blocks for non-512 byte sector size device
In reply to Greg Kroah-HartmanFrom: Yuezhang Mo <[email protected]>
commit 39c1ce8eafc0ff64fb9e28536ccc7df6a8e2999d upstream.
inode->i_blocks is not real number of blocks, but 512 byte ones.
--- fs/exfat/file.c | 3 +-- fs/exfat/inode.c | 6 ++---- fs/exfat/namei.c | 2 +- fs/exfat/super.c | 3 +-- 4 files changed, 5 insertions(+), 9 deletions(-)
fs/exfat/file.c +1 -2
@@ -250,8 +250,7 @@ void exfat_truncate(struct inode *inode,else mark_inode_dirty (inode); - inode->i_blocks =round_up (i_size_read (inode), sbi->cluster_size) >> - inode->i_blkbits; + inode->i_blocks =round_up (i_size_read (inode), sbi->cluster_size) >>9 ; write_size: aligned_size =i_size_read (inode);if (aligned_size & (blocksize -1 )) {
fs/exfat/inode.c +2 -4
@@ -242,8 +242,7 @@ static int exfat_map_cluster(struct inodreturn err; }/* end of if != DIR_DELETED */ - inode->i_blocks += - num_to_be_allocated << sbi->sect_per_clus_bits; + inode->i_blocks +=EXFAT_CLU_TO_B (num_to_be_allocated, sbi) >>9 ;/* * Move *clu pointer along FAT chains (hole care) because the
@@ -600,8 +599,7 @@ static int exfat_fill_inode(struct inodeexfat_save_attr (inode, info->attr); - inode->i_blocks =round_up (i_size_read (inode), sbi->cluster_size) >> - inode->i_blkbits; + inode->i_blocks =round_up (i_size_read (inode), sbi->cluster_size) >>9 ; inode->i_mtime = info->mtime; inode->i_ctime = info->mtime; ei->i_crtime = info->crtime;
fs/exfat/namei.c +1 -1
@@ -398,7 +398,7 @@ static int exfat_find_empty_entry(struct ei->i_size_ondisk += sbi->cluster_size; ei->i_size_aligned += sbi->cluster_size; ei->flags = p_dir->flags; - inode->i_blocks +=1 << sbi->sect_per_clus_bits; + inode->i_blocks += sbi->cluster_size >>9 ; }return dentry;
fs/exfat/super.c +1 -2
@@ -364,8 +364,7 @@ static int exfat_read_root(struct inode inode->i_op = &exfat_dir_inode_operations; inode->i_fop = &exfat_dir_operations; - inode->i_blocks =round_up (i_size_read (inode), sbi->cluster_size) >> - inode->i_blkbits; + inode->i_blocks =round_up (i_size_read (inode), sbi->cluster_size) >>9 ; ei->i_pos = ((loff_t )sbi->root_dir <<32 ) |0xffffffff ; ei->i_size_aligned =i_size_read (inode); ei->i_size_ondisk =i_size_read (inode);
Greg Kroah-Hartman
maintainerPATCH 344/529 f2fs: fix information leak in f2fs_move_inline_dirents()
In reply to Greg Kroah-HartmanFrom: Eric Biggers <[email protected]>
commit 9a5571cff4ffcfc24847df9fd545cc5799ac0ee5 upstream.
When converting an inline directory to a regular one, f2fs is leaking uninitialized memory to disk because it doesn't initialize the entire directory block. Fix this by zero-initializing the block.
This bug was introduced by commit 4ec17d688d74 ("f2fs: avoid unneeded initializing when converting inline dentry"), which didn't consider the security implications of leaking uninitialized memory to disk.
This was found by running xfstest generic/435 on a KMSAN-enabled kernel.
--- fs/f2fs/inline.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
fs/f2fs/inline.c +6 -7
@@ -420,18 +420,17 @@ static int f2fs_move_inline_dirents(stru dentry_blk =page_address (page); +/* +* Start by zeroing the full block, to ensure that all unused space is +* zeroed and no uninitialized memory is leaked to disk. +*/ +memset (dentry_blk,0 ,F2FS_BLKSIZE ); +make_dentry_ptr_inline (dir, &src, inline_dentry);make_dentry_ptr_block (dir, &dst, dentry_blk);/* copy data from inline dentry block to new dentry block */ memcpy (dst.bitmap, src.bitmap, src.nr_bitmap); -memset (dst.bitmap + src.nr_bitmap,0 , dst.nr_bitmap - src.nr_bitmap); -/* -* we do not need to zero out remainder part of dentry and filename -* field, since we have used bitmap for marking the usage status of -* them, besides, we can also ignore copying/zeroing reserved space -* of dentry block, because them haven't been used so far. -*/ memcpy (dst.dentry, src.dentry,SIZE_OF_DIR_ENTRY * src.max);memcpy (dst.filename, src.filename, src.max *F2FS_SLOT_LEN );
Greg Kroah-Hartman
maintainerPATCH 345/529 f2fs: fix cgroup writeback accounting with fs-layer encryption
In reply to Greg Kroah-HartmanFrom: Eric Biggers <[email protected]>
commit 844545c51a5b2a524b22a2fe9d0b353b827d24b4 upstream.
When writing a page from an encrypted file that is using filesystem-layer encryption (not inline encryption), f2fs encrypts the pagecache page into a bounce page, then writes the bounce page.
It also passes the bounce page to wbc_account_cgroup_owner(). That's incorrect, because the bounce page is a newly allocated temporary page that doesn't have the memory cgroup of the original pagecache page. This makes wbc_account_cgroup_owner() not account the I/O to the owner of the pagecache page as it should.
Fix this by always passing the pagecache page towbc_account_cgroup_owner().
--- fs/f2fs/data.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
fs/f2fs/data.c +3 -3
@@ -721,7 +721,7 @@ int f2fs_submit_page_bio(struct f2fs_io_ }if (fio->io_wbc && !is_read_io (fio->op)) -wbc_account_cgroup_owner (fio->io_wbc, page,PAGE_SIZE ); +wbc_account_cgroup_owner (fio->io_wbc, fio->page,PAGE_SIZE );__attach_io_flag (fio);bio_set_op_attrs (bio, fio->op, fio->op_flags);
@@ -929,7 +929,7 @@ alloc_new: }if (fio->io_wbc) -wbc_account_cgroup_owner (fio->io_wbc, page,PAGE_SIZE ); +wbc_account_cgroup_owner (fio->io_wbc, fio->page,PAGE_SIZE );inc_page_count (fio->sbi,WB_DATA_TYPE (page));
@@ -1003,7 +1003,7 @@ alloc_new: }if (fio->io_wbc) -wbc_account_cgroup_owner (fio->io_wbc, bio_page,PAGE_SIZE ); +wbc_account_cgroup_owner (fio->io_wbc, fio->page,PAGE_SIZE ); io->last_block_in_bio = fio->new_blkaddr;f2fs_trace_ios (fio,0 );
Greg Kroah-Hartman
maintainerPATCH 346/529 ocfs2: fix defrag path triggering jbd2 ASSERT
In reply to Greg Kroah-HartmanFrom: Heming Zhao via Ocfs2-devel <[email protected]>
commit 60eed1e3d45045623e46944ebc7c42c30a4350f0 upstream.
code path:
ocfs2_ioctl_move_extents
ocfs2_move_extents
ocfs2_defrag_extent
__ocfs2_move_extent
+ ocfs2_journal_access_di
+ ocfs2_split_extent //sub-paths call jbd2_journal_restart
+ ocfs2_journal_dirty //crash by jbs2 ASSERT
crash stacks:
PID: 11297 TASK: ffff974a676dcd00 CPU: 67 COMMAND: "defragfs.ocfs2"
#0 [ffffb25d8dad3900] machine_kexec at ffffffff8386fe01
#1 [ffffb25d8dad3958] __crash_kexec at ffffffff8395959d
#2 [ffffb25d8dad3a20] crash_kexec at ffffffff8395a45d
#3 [ffffb25d8dad3a38] oops_end at ffffffff83836d3f
#4 [ffffb25d8dad3a58] do_trap at ffffffff83833205
#5 [ffffb25d8dad3aa0] do_invalid_op at ffffffff83833aa6
#6 [ffffb25d8dad3ac0] invalid_op at ffffffff84200d18
[exception RIP: jbd2_journal_dirty_metadata+0x2ba]
RIP: ffffffffc09ca54a RSP: ffffb25d8dad3b70 RFLAGS: 00010207
RAX: 0000000000000000 RBX: ffff9706eedc5248 RCX: 0000000000000000
RDX: 0000000000000001 RSI: ffff97337029ea28 RDI: ffff9706eedc5250
RBP: ffff9703c3520200 R8: 000000000f46b0b2 R9: 0000000000000000
R10: 0000000000000001 R11: 00000001000000fe R12: ffff97337029ea28
R13: 0000000000000000 R14: ffff9703de59bf60 R15: ffff9706eedc5250
ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 #7 [ffffb25d8dad3ba8] ocfs2_journal_dirty at ffffffffc137fb95 [ocfs2] #8 [ffffb25d8dad3be8] __ocfs2_move_extent at ffffffffc139a950 [ocfs2] #9 [ffffb25d8dad3c80] ocfs2_defrag_extent at ffffffffc139b2d2 [ocfs2]
Analysis
This bug has the same root cause of 'commit 7f27ec978b0e ("ocfs2: call ocfs2_journal_access_di() before ocfs2_journal_dirty() in ocfs2_write_end_nolock()")'. For this bug, jbd2_journal_restart() is called by ocfs2_split_extent() during defragmenting.
How to fix
For ocfs2_split_extent() can handle journal operations totally by itself. Caller doesn't need to call journal access/dirty pair, and caller only needs to call journal start/stop pair. The fix method is to remove journal access/dirty from __ocfs2_move_extent().
The discussion for this patch:
https://oss.oracle.com/pipermail/ocfs2-devel/2023-February/000647.html
--- fs/ocfs2/move_extents.c | 10 ---------- 1 file changed, 10 deletions(-)
fs/ocfs2/move_extents.c +0 -10
@@ -107,14 +107,6 @@ static int __ocfs2_move_extent(handle_t*/ replace_rec.e_flags = ext_flags & ~OCFS2_EXT_REFCOUNTED ; - ret =ocfs2_journal_access_di (handle,INODE_CACHE (inode), - context->et.et_root_bh, -OCFS2_JOURNAL_ACCESS_WRITE ); -if (ret) { -mlog_errno (ret); - goto out; - } - ret =ocfs2_split_extent (handle, &context->et, path, index, &replace_rec, context->meta_ac, &context->dealloc);
@@ -123,8 +115,6 @@ static int __ocfs2_move_extent(handle_t goto out; } -ocfs2_journal_dirty (handle, context->et.et_root_bh); - context->new_phys_cpos = new_p_cpos;/*
Greg Kroah-Hartman
maintainerPATCH 347/529 ocfs2: fix non-auto defrag path not working issue
In reply to Greg Kroah-HartmanFrom: Heming Zhao via Ocfs2-devel <[email protected]>
commit 236b9254f8d1edc273ad88b420aa85fbd84f492d upstream.
This fixes three issues on move extents ioctl without auto defrag:
a) In ocfs2_find_victim_alloc_group(), we have to convert bits to block first in case of global bitmap.
b) In ocfs2_probe_alloc_group(), when finding enough bits in block group bitmap, we have to back off move_len to start pos as well, otherwise it may corrupt filesystem.
c) In ocfs2_ioctl_move_extents(), set me_threshold both for non-auto and auto defrag paths. Otherwise it will set move_max_hop to 0 and finally cause unexpectedly ENOSPC error.
Currently there are no tools triggering the above issues since defragfs.ocfs2 enables auto defrag by default. Tested with manually changing defragfs.ocfs2 to run non auto defrag path.
--- fs/ocfs2/move_extents.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-)
fs/ocfs2/move_extents.c +13 -11
@@ -436,7 +436,7 @@ static int ocfs2_find_victim_alloc_group bg = (struct ocfs2_group_desc *)gd_bh->b_data;if (vict_blkno < (le64_to_cpu (bg->bg_blkno) + -le16_to_cpu (bg->bg_bits))) { + (le16_to_cpu (bg->bg_bits) << bits_per_unit))) { *ret_bh = gd_bh; *vict_bit = (vict_blkno - blkno) >>
@@ -551,6 +551,7 @@ static void ocfs2_probe_alloc_group(stru last_free_bits++;if (last_free_bits == move_len) { + i -= move_len; *goal_bit = i; *phys_cpos = base_cpos + i;break ;
@@ -1022,18 +1023,19 @@ int ocfs2_ioctl_move_extents(struct file context->range = ⦥ +/* +* ok, the default theshold for the defragmentation +* is 1M, since our maximum clustersize was 1M also. +* any thought? +*/ +if (!range.me_threshold) + range.me_threshold =1024 *1024 ; + +if (range.me_threshold >i_size_read (inode)) + range.me_threshold =i_size_read (inode); +if (range.me_flags &OCFS2_MOVE_EXT_FL_AUTO_DEFRAG ) { context->auto_defrag =1 ; -/* -* ok, the default theshold for the defragmentation -* is 1M, since our maximum clustersize was 1M also. -* any thought? -*/ -if (!range.me_threshold) - range.me_threshold =1024 *1024 ; - -if (range.me_threshold >i_size_read (inode)) - range.me_threshold =i_size_read (inode);if (range.me_flags &OCFS2_MOVE_EXT_FL_PART_DEFRAG ) context->partial =1 ;
Greg Kroah-Hartman
maintainerPATCH 348/529 udf: Truncate added extents on failed expansion
In reply to Greg Kroah-HartmanFrom: Jan Kara <[email protected]>
commit 70bfb3a8d661d4fdc742afc061b88a7f3fc9f500 upstream.
When a file expansion failed because we didn't have enough space for indirect extents make sure we truncate extents created so far so that we don't leave extents beyond EOF.
--- fs/udf/inode.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
fs/udf/inode.c +11 -4
@@ -525,8 +525,10 @@ static int udf_do_extend_file(struct ino }if (fake) { -udf_add_aext (inode, last_pos, &last_ext->extLocation, - last_ext->extLength,1 ); + err =udf_add_aext (inode, last_pos, &last_ext->extLocation, + last_ext->extLength,1 ); +if (err <0 ) + goto out_err; count++; }else {struct kernel_lb_addr tmploc;
@@ -560,7 +562,7 @@ static int udf_do_extend_file(struct ino err =udf_add_aext (inode, last_pos, &last_ext->extLocation, last_ext->extLength,1 );if (err) -return err; + goto out_err; count++; }if (new_block_bytes) {
@@ -569,7 +571,7 @@ static int udf_do_extend_file(struct ino err =udf_add_aext (inode, last_pos, &last_ext->extLocation, last_ext->extLength,1 );if (err) -return err; + goto out_err; count++; }
@@ -583,6 +585,11 @@ out:return -EIO ;return count; +out_err: +/* Remove extents we've created so far */ +udf_clear_extent_cache (inode); +udf_truncate_extents (inode); +return err; }/* Extend the final block of the file to final_block_len bytes */
Greg Kroah-Hartman
maintainerPATCH 349/529 udf: Do not bother merging very long extents
In reply to Greg Kroah-HartmanFrom: Jan Kara <[email protected]>
commit 53cafe1d6d8ef9f93318e5bfccc0d24f27d41ced upstream.
When merging very long extents we try to push as much length as possible to the first extent. However this is unnecessarily complicated and not really worth the trouble. Furthermore there was a bug in the logic resulting in corrupting extents in the file as syzbot reproducer shows. So just don't bother with the merging of extents that are too long together.
--- fs/udf/inode.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-)
fs/udf/inode.c +2 -17
@@ -1093,23 +1093,8 @@ static void udf_merge_extents(struct ino blocksize - 1) >> blocksize_bits)))) {if (((li->extLength &UDF_EXTENT_LENGTH_MASK ) + - (lip1->extLength &UDF_EXTENT_LENGTH_MASK ) + - blocksize -1 ) & ~UDF_EXTENT_LENGTH_MASK ) { - lip1->extLength = (lip1->extLength - - (li->extLength & -UDF_EXTENT_LENGTH_MASK ) + -UDF_EXTENT_LENGTH_MASK ) & - ~(blocksize -1 ); - li->extLength = (li->extLength & -UDF_EXTENT_FLAG_MASK ) + - (UDF_EXTENT_LENGTH_MASK +1 ) - - blocksize; - lip1->extLocation.logicalBlockNum = - li->extLocation.logicalBlockNum + - ((li->extLength & -UDF_EXTENT_LENGTH_MASK ) >> - blocksize_bits); - }else { + (lip1->extLength &UDF_EXTENT_LENGTH_MASK ) + + blocksize -1 ) <=UDF_EXTENT_LENGTH_MASK ) { li->extLength = lip1->extLength + (((li->extLength & UDF_EXTENT_LENGTH_MASK) +
Greg Kroah-Hartman
maintainerPATCH 350/529 udf: Do not update file length for failed writes to inline files
In reply to Greg Kroah-HartmanFrom: Jan Kara <[email protected]>
commit 256fe4162f8b5a1625b8603ca5f7ff79725bfb47 upstream.
When write to inline file fails (or happens only partly), we still updated length of inline data as if the whole write succeeded. Fix the update of length of inline data to happen only if the write succeeds.
--- fs/udf/file.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-)
fs/udf/file.c +12 -14
@@ -147,26 +147,24 @@ static ssize_t udf_file_write_iter(struc goto out;down_write (&iinfo->i_data_sem); -if (iinfo->i_alloc_type ==ICBTAG_FLAG_AD_IN_ICB ) { -loff_t end = iocb->ki_pos +iov_iter_count (from); - -if (inode->i_sb->s_blocksize < - (udf_file_entry_alloc_offset (inode) + end)) { - err =udf_expand_file_adinicb (inode); -if (err) { -inode_unlock (inode); -udf_debug ("udf_expand_adinicb: err=%d\n" , err); -return err; - } - }else { - iinfo->i_lenAlloc =max (end, inode->i_size); -up_write (&iinfo->i_data_sem); +if (iinfo->i_alloc_type ==ICBTAG_FLAG_AD_IN_ICB && + inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset (inode) + + iocb->ki_pos +iov_iter_count (from))) { + err =udf_expand_file_adinicb (inode); +if (err) { +inode_unlock (inode); +udf_debug ("udf_expand_adinicb: err=%d\n" , err); +return err; } }else up_write (&iinfo->i_data_sem); retval =__generic_file_write_iter (iocb, from); out: +down_write (&iinfo->i_data_sem); +if (iinfo->i_alloc_type ==ICBTAG_FLAG_AD_IN_ICB && retval >0 ) + iinfo->i_lenAlloc = inode->i_size; +up_write (&iinfo->i_data_sem);inode_unlock (inode);if (retval >0 ) {
Greg Kroah-Hartman
maintainerPATCH 351/529 udf: Preserve link count of system files
In reply to Greg Kroah-HartmanFrom: Jan Kara <[email protected]>
commit fc8033a34a3ca7d23353e645e6dde5d364ac5f12 upstream.
System files in UDF filesystem have link count 0. To not confuse VFS we fudge the link count to be 1 when reading such inodes however we forget to restore the link count of 0 when writing such inodes. Fix that.
--- fs/udf/inode.c | 9 +++++++-- fs/udf/super.c | 1 + fs/udf/udf_i.h | 3 ++- 3 files changed, 10 insertions(+), 3 deletions(-)
fs/udf/inode.c +7 -2
@@ -1385,6 +1385,7 @@ reread: ret = -EIO ; goto out; } + iinfo->i_hidden = hidden_inode; iinfo->i_unique =0 ; iinfo->i_lenEAttr =0 ; iinfo->i_lenExtents =0 ;
@@ -1720,8 +1721,12 @@ static int udf_update_inode(struct inodeif (S_ISDIR (inode->i_mode) && inode->i_nlink >0 ) fe->fileLinkCount =cpu_to_le16 (inode->i_nlink -1 ); -else - fe->fileLinkCount =cpu_to_le16 (inode->i_nlink); +else { +if (iinfo->i_hidden) + fe->fileLinkCount =cpu_to_le16 (0 ); +else + fe->fileLinkCount =cpu_to_le16 (inode->i_nlink); + } fe->informationLength =cpu_to_le64 (inode->i_size);
fs/udf/super.c +1 -0
@@ -147,6 +147,7 @@ static struct inode *udf_alloc_inode(str ei->i_next_alloc_goal =0 ; ei->i_strat4096 =0 ; ei->i_streamdir =0 ; + ei->i_hidden =0 ;init_rwsem (&ei->i_data_sem); ei->cached_extent.lstart =-1 ;spin_lock_init (&ei->i_extent_cache_lock);
fs/udf/udf_i.h +2 -1
@@ -44,7 +44,8 @@ struct udf_inode_info { unsigned i_use : 1; /* unallocSpaceEntry */ unsigned i_strat4096 : 1; unsigned i_streamdir : 1; - unsigned reserved : 25; + unsigned i_hidden : 1; /* hidden system inode */ + unsigned reserved : 24;__u8 *i_data;struct kernel_lb_addr i_locStreamdir;__u64 i_lenStreams;
Greg Kroah-Hartman
maintainerPATCH 352/529 udf: Detect system inodes linked into directory hierarchy
In reply to Greg Kroah-HartmanFrom: Jan Kara <[email protected]>
commit 85a37983ec69cc9fcd188bc37c4de15ee326355a upstream.
When UDF filesystem is corrupted, hidden system inodes can be linked into directory hierarchy which is an avenue for further serious corruption of the filesystem and kernel confusion as noticed by syzbot fuzzed images. Refuse to access system inodes linked into directory hierarchy and vice versa.
--- fs/udf/inode.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
fs/udf/inode.c +6 -1
@@ -1897,8 +1897,13 @@ struct inode *__udf_iget(struct super_blif (!inode)return ERR_PTR (-ENOMEM ); -if (!(inode->i_state &I_NEW )) +if (!(inode->i_state &I_NEW )) { +if (UDF_I (inode)->i_hidden != hidden_inode) { +iput (inode); +return ERR_PTR (-EFSCORRUPTED ); + }return inode; + }memcpy (&UDF_I (inode)->i_location, ino,sizeof (struct kernel_lb_addr )); err =udf_read_inode (inode, hidden_inode);
Greg Kroah-Hartman
maintainerPATCH 353/529 udf: Fix file corruption when appending just after end of preallocated extent
In reply to Greg Kroah-HartmanFrom: Jan Kara <[email protected]>
commit 36ec52ea038b18a53e198116ef7d7e70c87db046 upstream.
When we append new block just after the end of preallocated extent, the code in inode_getblk() wrongly determined we're going to use the preallocated extent which resulted in adding block into a wrong logical offset in the file. Sequence like this manifests it:
xfs_io -f -c "pwrite 0x2cacf 0xd122" -c "truncate 0x2dd6f" \
-c "pwrite 0x27fd9 0x69a9" -c "pwrite 0x32981 0x7244" <file>
The code that determined the use of preallocated extent is actually stale because udf_do_extend_file() does not create preallocation anymore so after calling that function we are sure there's no usable preallocation. Just remove the faulty condition.
--- fs/udf/inode.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-)
fs/udf/inode.c +11 -13
@@ -804,19 +804,17 @@ static sector_t inode_getblk(struct inod c =0 ; offset =0 ; count += ret; -/* We are not covered by a preallocated extent? */ -if ((laarr[0 ].extLength &UDF_EXTENT_FLAG_MASK ) != -EXT_NOT_RECORDED_ALLOCATED ) { -/* Is there any real extent? - otherwise we overwrite -* the fake one... */ -if (count) - c = !c; - laarr[c].extLength =EXT_NOT_RECORDED_NOT_ALLOCATED | - inode->i_sb->s_blocksize; -memset (&laarr[c].extLocation,0x00 , -sizeof (struct kernel_lb_addr )); - count++; - } +/* +* Is there any real extent? - otherwise we overwrite the fake +* one... +*/ +if (count) + c = !c; + laarr[c].extLength =EXT_NOT_RECORDED_NOT_ALLOCATED | + inode->i_sb->s_blocksize; +memset (&laarr[c].extLocation,0x00 , +sizeof (struct kernel_lb_addr )); + count++; endnum = c +1 ; lastblock =1 ; }else {
Greg Kroah-Hartman
maintainerPATCH 354/529 KVM: Destroy target device if coalesced MMIO unregistration fails
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit b1cb1fac22abf102ffeb29dd3eeca208a3869d54 upstream.
Destroy and free the target coalesced MMIO device if unregistering said device fails. As clearly noted in the code, kvm_io_bus_unregister_dev() does not destroy the target device.
BUG: memory leak
unreferenced object 0xffff888112a54880 (size 64):
comm "syz-executor.2", pid 5258, jiffies 4297861402 (age 14.129s)
hex dump (first 32 bytes):
38 c7 67 15 00 c9 ff ff 38 c7 67 15 00 c9 ff ff 8.g.....8.g.....
e0 c7 e1 83 ff ff ff ff 00 30 67 15 00 c9 ff ff .........0g.....
backtrace:
[<0000000006995a8a>] kmalloc include/linux/slab.h:556 [inline]
[<0000000006995a8a>] kzalloc include/linux/slab.h:690 [inline]
[<0000000006995a8a>] kvm_vm_ioctl_register_coalesced_mmio+0x8e/0x3d0 arch/x86/kvm/../../../virt/kvm/coalesced_mmio.c:150
[<00000000022550c2>] kvm_vm_ioctl+0x47d/0x1600 arch/x86/kvm/../../../virt/kvm/kvm_main.c:3323
[<000000008a75102f>] vfs_ioctl fs/ioctl.c:46 [inline]
[<000000008a75102f>] file_ioctl fs/ioctl.c:509 [inline]
[<000000008a75102f>] do_vfs_ioctl+0xbab/0x1160 fs/ioctl.c:696
[<0000000080e3f669>] ksys_ioctl+0x76/0xa0 fs/ioctl.c:713
[<0000000059ef4888>] __do_sys_ioctl fs/ioctl.c:720 [inline]
[<0000000059ef4888>] __se_sys_ioctl fs/ioctl.c:718 [inline]
[<0000000059ef4888>] __x64_sys_ioctl+0x6f/0xb0 fs/ioctl.c:718
[<000000006444fa05>] do_syscall_64+0x9f/0x4e0 arch/x86/entry/common.c:290
[<000000009a4ed50b>] entry_SYSCALL_64_after_hwframe+0x49/0xbe
BUG: leak checking failed--- virt/kvm/coalesced_mmio.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
virt/kvm/coalesced_mmio.c +5 -3
@@ -187,15 +187,17 @@ int kvm_vm_ioctl_unregister_coalesced_mm r =kvm_io_bus_unregister_dev (kvm, zone->pio ?KVM_PIO_BUS :KVM_MMIO_BUS , &dev->dev); +kvm_iodevice_destructor (&dev->dev); +/* * On failure, unregister destroys all devices on the * bus _except_ the target device, i.e. coalesced_zones -* has been modified. No need to restart the walk as -* there aren't any zones left. +* has been modified. Bail after destroying the target +* device, there's no need to restart the walk as there +* aren't any zones left. */ if (r)break ; -kvm_iodevice_destructor (&dev->dev); } }
Greg Kroah-Hartman
maintainerPATCH 355/529 KVM: x86: Inject #GP if WRMSR sets reserved bits in APIC Self-IPI
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit ba5838abb05334e4abfdff1490585c7f365e0424 upstream.
Inject a #GP if the guest attempts to set reserved bits in the x2APIC-only Self-IPI register. Bits 7:0 hold the vector, all other bits are reserved.
--- arch/x86/kvm/lapic.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
arch/x86/kvm/lapic.c +7 -3
@@ -2115,10 +2115,14 @@ int kvm_lapic_reg_write(struct kvm_lapicbreak ;case APIC_SELF_IPI : -if (apic_x2apic_mode (apic)) -kvm_apic_send_ipi (apic,APIC_DEST_SELF | (val &APIC_VECTOR_MASK ),0 ); -else +/* +* Self-IPI exists only when x2APIC is enabled. Bits 7:0 hold +* the vector, everything else is reserved. +*/ +if (!apic_x2apic_mode (apic) || (val & ~APIC_VECTOR_MASK )) ret =1 ; +else +kvm_apic_send_ipi (apic,APIC_DEST_SELF | val,0 );break ;default : ret =1 ;
Greg Kroah-Hartman
maintainerPATCH 356/529 KVM: s390: disable migration mode when dirty tracking is disabled
In reply to Greg Kroah-HartmanFrom: Nico Boehr <[email protected]>
commit f2d3155e2a6bac44d16f04415a321e8707d895c6 upstream.
Migration mode is a VM attribute which enables tracking of changes in storage attributes (PGSTE). It assumes dirty tracking is enabled on all memslots to keep a dirty bitmap of pages with changed storage attributes.
When enabling migration mode, we currently check that dirty tracking is enabled for all memslots. However, userspace can disable dirty tracking without disabling migration mode.
Since migration mode is pointless with dirty tracking disabled, disable migration mode whenever userspace disables dirty tracking on any slot.
Also update the documentation to clarify that dirty tracking must be enabled when enabling migration mode, which is already enforced by the code in kvm_s390_vm_start_migration().
Also highlight in the documentation for KVM_S390_GET_CMMA_BITS that it can now fail with -EINVAL when dirty tracking is disabled while migration mode is on. Move all the error codes to a table so this stays readable.
To disable migration mode, slots_lock should be held, which is taken in kvm_set_memory_region() and thus held in kvm_arch_prepare_memory_region().
Restructure the prepare code a bit so all the sanity checking is done before disabling migration mode. This ensures migration mode isn't disabled when some sanity check fails.
Message-Id: <[email protected]>
--- Documentation/virt/kvm/api.rst | 18 ++++++++++++------ Documentation/virt/kvm/devices/vm.rst | 4 ++++ arch/s390/kvm/kvm-s390.c | 17 +++++++++++++++++ 3 files changed, 33 insertions(+), 6 deletions(-)
Documentation/virt/kvm/api.rst +12 -6
@@ -4031,6 +4031,18 @@ not holding a previously reported uncorr :Parameters: struct kvm_s390_cmma_log (in, out) :Returns: 0 on success, a negative value on error +Errors: + + ====== ============================================================= + ENOMEM not enough memory can be allocated to complete the task + ENXIO if CMMA is not enabled + EINVAL if KVM_S390_CMMA_PEEK is not set but migration mode was not enabled + EINVAL if KVM_S390_CMMA_PEEK is not set but dirty tracking has been + disabled (and thus migration mode was automatically disabled) + EFAULT if the userspace address is invalid or if no page table is + present for the addresses (e.g. when using hugepages). + ====== ============================================================= + This ioctl is used to get the values of the CMMA bits on the s390 architecture. It is meant to be used in two scenarios:
@@ -4111,12 +4123,6 @@ mask is unused. values points to the userspace buffer where the result will be stored. -This ioctl can fail with -ENOMEM if not enough memory can be allocated to -complete the task, with -ENXIO if CMMA is not enabled, with -EINVAL if -KVM_S390_CMMA_PEEK is not set but migration mode was not enabled, with --EFAULT if the userspace address is invalid or if no page table is -present for the addresses (e.g. when using hugepages). - 4.108 KVM_S390_SET_CMMA_BITS ----------------------------
Documentation/virt/kvm/devices/vm.rst +4 -0
@@ -302,6 +302,10 @@ Allows userspace to start migration mode Setting this attribute when migration mode is already active will have no effects. +Dirty tracking must be enabled on all memslots, else -EINVAL is returned. When +dirty tracking is disabled on any memslot, migration mode is automatically +stopped. + :Parameters: none :Returns: -ENOMEM if there is not enough free memory to start migration mode; -EINVAL if the state of the VM is invalid (e.g. no memory defined);
arch/s390/kvm/kvm-s390.c +17 -0
@@ -5012,6 +5012,23 @@ int kvm_arch_prepare_memory_region(struc/* When we are protected, we should not change the memory slots */ if (kvm_s390_pv_get_handle (kvm))return -EINVAL ; + +if (!kvm->arch.migration_mode) +return 0 ; + +/* +* Turn off migration mode when: +* - userspace creates a new memslot with dirty logging off, +* - userspace modifies an existing memslot (MOVE or FLAGS_ONLY) and +* dirty logging is turned off. +* Migration mode expects dirty page logging being enabled to store +* its dirty bitmap. +*/ +if (change !=KVM_MR_DELETE && + !(mem->flags &KVM_MEM_LOG_DIRTY_PAGES )) +WARN (kvm_s390_vm_stop_migration (kvm), +"Failed to stop migration mode" ); +return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 357/529 x86/virt: Force GIF=1 prior to disabling SVM (for reboot flows)
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit 6a3236580b0b1accc3976345e723104f74f6f8e6 upstream.
Set GIF=1 prior to disabling SVM to ensure that INIT is recognized if the kernel is disabling SVM in an emergency, e.g. if the kernel is about to jump into a crash kernel or may reboot without doing a full CPU RESET. If GIF is left cleared, the new kernel (or firmware) will be unabled to awaken APs. Eat faults on STGI (due to EFER.SVME=0) as it's possible that SVM could be disabled via NMI shootdown between reading EFER.SVME and executing STGI.
--- arch/x86/include/asm/virtext.h | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
arch/x86/include/asm/virtext.h +15 -1
@@ -120,7 +120,21 @@ static inline void cpu_svm_disable(void)wrmsrl (MSR_VM_HSAVE_PA ,0 );rdmsrl (MSR_EFER , efer); -wrmsrl (MSR_EFER , efer & ~EFER_SVME ); +if (efer &EFER_SVME ) { +/* +* Force GIF=1 prior to disabling SVM to ensure INIT and NMI +* aren't blocked, e.g. if a fatal error occurred between CLGI +* and STGI. Note, STGI may #UD if SVM is disabled from NMI +* context between reading EFER and executing STGI. In that +* case, GIF must already be set, otherwise the NMI would have +* been blocked, so just eat the fault. +*/ + asm_volatile_goto("1: stgi\n\t" + _ASM_EXTABLE(1b, %l[fault]) + ::: "memory" : fault); +fault: + wrmsrl(MSR_EFER, efer & ~EFER_SVME); + } }/** Makes sure SVM is disabled, if it is supported on the CPU
Greg Kroah-Hartman
maintainerPATCH 358/529 x86/crash: Disable virt in core NMI crash handler to avoid double shootdown
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit 26044aff37a5455b19a91785086914fd33053ef4 upstream.
Disable virtualization in crash_nmi_callback() and rework the emergency_vmx_disable_all() path to do an NMI shootdown if and only if a
shootdown has not already occurred. NMI crash shootdown fundamentally
can't support multiple invocations as responding CPUs are deliberately put into halt state without unblocking NMIs. But, the emergency reboot path doesn't have any work of its own, it simply cares about disabling virtualization, i.e. so long as a shootdown occurred, emergency reboot doesn't care who initiated the shootdown, or when.
If "crash_kexec_post_notifiers" is specified on the kernel command line, panic() will invoke crash_smp_send_stop() and result in a second call to nmi_shootdown_cpus() during native_machine_emergency_restart().
Invoke the callback _before_ disabling virtualization, as the current VMCS needs to be cleared before doing VMXOFF. Note, this results in a subtle change in ordering between disabling virtualization and stopping Intel PT on the responding CPUs. While VMX and Intel PT do interact, VMXOFF and writes to MSR_IA32_RTIT_CTL do not induce faults between one another, which is all that matters when panicking.
Harden nmi_shootdown_cpus() against multiple invocations to try and capture any such kernel bugs via a WARN instead of hanging the system during a crash/dump, e.g. prior to the recent hardening of register_nmi_handler(), re-registering the NMI handler would trigger a double list_add() and hang the system if CONFIG_BUG_ON_DATA_CORRUPTION=y.
list_add double add: new=ffffffff82220800, prev=ffffffff8221cfe8, next=ffffffff82220800.
WARNING: CPU: 2 PID: 1319 at lib/list_debug.c:29 __list_add_valid+0x67/0x70 Call Trace: __register_nmi_handler+0xcf/0x130 nmi_shootdown_cpus+0x39/0x90 native_machine_emergency_restart+0x1c9/0x1d0 panic+0x237/0x29b
Extract the disabling logic to a common helper to deduplicate code, and to prepare for doing the shootdown in the emergency reboot path if SVM is supported.
Note, prior to commit ed72736183c4 ("x86/reboot: Force all cpus to exit VMX root if VMX is supported"), nmi_shootdown_cpus() was subtly protected against a second invocation by a cpu_vmx_enabled() check as the kdump handler would disable VMX if it ran first.
--- arch/x86/include/asm/reboot.h | 2 + arch/x86/kernel/crash.c | 17 ---------- arch/x86/kernel/reboot.c | 65 ++++++++++++++++++++++++++++++++++-------- 3 files changed, 56 insertions(+), 28 deletions(-)
arch/x86/include/asm/reboot.h +2 -0
@@ -25,6 +25,8 @@ void __noreturn machine_real_restart(uns#define MRR_BIOS 0#define MRR_APM 1 +void cpu_emergency_disable_virtualization (void ); +typedef void (*nmi_shootdown_cb )(int ,struct pt_regs *);void nmi_panic_self_stop (struct pt_regs *regs);void nmi_shootdown_cpus (nmi_shootdown_cb callback);
arch/x86/kernel/crash.c +1 -16
@@ -37,7 +37,6 @@#include <linux/kdebug.h> #include <asm/cpu.h> #include <asm/reboot.h> -#include <asm/virtext.h> #include <asm/intel_pt.h> #include <asm/crash.h> #include <asm/cmdline.h>
@@ -94,15 +93,6 @@ static void kdump_nmi_callback(int cpu,*/ cpu_crash_vmclear_loaded_vmcss (); -/* Disable VMX or SVM if needed. -* -* We need to disable virtualization on all CPUs. -* Having VMX or SVM enabled on any CPU may break rebooting -* after the kdump kernel has finished its task. -*/ -cpu_emergency_vmxoff (); -cpu_emergency_svm_disable (); -/* * Disable Intel PT to stop its logging */
@@ -161,12 +151,7 @@ void native_machine_crash_shutdown(struc*/ cpu_crash_vmclear_loaded_vmcss (); -/* Booting kdump kernel with VMX or SVM enabled won't work, -* because (among other limitations) we can't disable paging -* with the virt flags. -*/ -cpu_emergency_vmxoff (); -cpu_emergency_svm_disable (); +cpu_emergency_disable_virtualization ();/* * Disable Intel PT to stop its logging
arch/x86/kernel/reboot.c +53 -12
114 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 359/529 x86/reboot: Disable virtualization in an emergency if SVM is supported
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit d81f952aa657b76cea381384bef1fea35c5fd266 upstream.
Disable SVM on all CPUs via NMI shootdown during an emergency reboot. Like VMX, SVM can block INIT, e.g. if the emergency reboot is triggered between CLGI and STGI, and thus can prevent bringing up other CPUs via INIT-SIPI-SIPI.
--- arch/x86/kernel/reboot.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-)
arch/x86/kernel/reboot.c +11 -12
@@ -530,27 +530,26 @@ static inline void kb_wait(void)static inline void nmi_shootdown_cpus_on_restart (void ); -/* Use NMIs as IPIs to tell all CPUs to disable virtualization */ -static void emergency_vmx_disable_all (void ) +static void emergency_reboot_disable_virtualization (void ) {/* Just make sure we won't change CPUs while doing this */ local_irq_disable ();/* -* Disable VMX on all CPUs before rebooting, otherwise we risk hanging -* the machine, because the CPU blocks INIT when it's in VMX root. +* Disable virtualization on all CPUs before rebooting to avoid hanging +* the system, as VMX and SVM block INIT when running in the host. * * We can't take any locks and we may be on an inconsistent state, so -* use NMIs as IPIs to tell the other CPUs to exit VMX root and halt. +* use NMIs as IPIs to tell the other CPUs to disable VMX/SVM and halt. * -* Do the NMI shootdown even if VMX if off on _this_ CPU, as that -* doesn't prevent a different CPU from being in VMX root operation. +* Do the NMI shootdown even if virtualization is off on _this_ CPU, as +* other CPUs may have virtualization enabled. */ -if (cpu_has_vmx ()) { -/* Safely force _this_ CPU out of VMX root operation. */ -__cpu_emergency_vmxoff (); +if (cpu_has_vmx () ||cpu_has_svm (NULL )) { +/* Safely force _this_ CPU out of VMX/SVM operation. */ +cpu_emergency_disable_virtualization (); -/* Halt and exit VMX root operation on the other CPUs. */ +/* Disable VMX/SVM and halt on other CPUs. */ nmi_shootdown_cpus_on_restart (); } }
@@ -587,7 +586,7 @@ static void native_machine_emergency_resunsigned short mode;if (reboot_emergency) -emergency_vmx_disable_all (); +emergency_reboot_disable_virtualization ();tboot_shutdown (TB_SHUTDOWN_REBOOT );
Greg Kroah-Hartman
maintainerPATCH 360/529 x86/reboot: Disable SVM, not just VMX, when stopping CPUs
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit a2b07fa7b93321c059af0c6d492cc9a4f1e390aa upstream.
Disable SVM and more importantly force GIF=1 when halting a CPU or rebooting the machine. Similar to VMX, SVM allows software to block INITs via CLGI, and thus can be problematic for a crash/reboot. The window for failure is smaller with SVM as INIT is only blocked while GIF=0, i.e. between CLGI and STGI, but the window does exist.
--- arch/x86/kernel/smp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
arch/x86/kernel/smp.c +3 -3
@@ -32,7 +32,7 @@#include <asm/mce.h> #include <asm/trace/irq_vectors.h> #include <asm/kexec.h> -#include <asm/virtext.h> +#include <asm/reboot.h> /* * Some notes on x86 processor bugs affecting SMP operation:
@@ -122,7 +122,7 @@ static int smp_stop_nmi_callback(unsigneif (raw_smp_processor_id () ==atomic_read (&stopping_cpu))return NMI_HANDLED ; -cpu_emergency_vmxoff (); +cpu_emergency_disable_virtualization ();stop_this_cpu (NULL );return NMI_HANDLED ;
@@ -134,7 +134,7 @@ static int smp_stop_nmi_callback(unsigneDEFINE_IDTENTRY_SYSVEC (sysvec_reboot) {ack_APIC_irq (); -cpu_emergency_vmxoff (); +cpu_emergency_disable_virtualization ();stop_this_cpu (NULL ); }
Greg Kroah-Hartman
maintainerPATCH 361/529 x86/kprobes: Fix __recover_optprobed_insn check optimizing logic
In reply to Greg Kroah-HartmanFrom: Yang Jihong <[email protected]>
commit 868a6fc0ca2407622d2833adefe1c4d284766c4c upstream.
Since the following commit:
commit f66c0447cca1 ("kprobes: Set unoptimized flag after unoptimizing code")
modified the update timing of the KPROBE_FLAG_OPTIMIZED, a optimized_kprobe may be in the optimizing or unoptimizing state when op.kp->flags has KPROBE_FLAG_OPTIMIZED and op->list is not empty.
The __recover_optprobed_insn check logic is incorrect, a kprobe in the unoptimizing state may be incorrectly determined as unoptimizing. As a result, incorrect instructions are copied.
The optprobe_queued_unopt function needs to be exported for invoking in arch directory.
--- arch/x86/kernel/kprobes/opt.c | 4 ++-- include/linux/kprobes.h | 1 + kernel/kprobes.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-)
arch/x86/kernel/kprobes/opt.c +2 -2
@@ -46,8 +46,8 @@ unsigned long __recover_optprobed_insn(k/* This function only handles jump-optimized kprobe */ if (kp &&kprobe_optimized (kp)) { op = container_of(kp, struct optimized_kprobe, kp); -/* If op->list is not empty, op is under optimizing */ -if (list_empty (&op->list)) +/* If op is optimized or under unoptimizing */ +if (list_empty (&op->list) ||optprobe_queued_unopt (op)) goto found; } }
include/linux/kprobes.h +1 -0
@@ -342,6 +342,7 @@ extern int proc_kprobes_optimization_han size_t *length, loff_t *ppos);#endif extern void wait_for_kprobe_optimizer (void ); +bool optprobe_queued_unopt (struct optimized_kprobe *op);#else static inline void wait_for_kprobe_optimizer (void ) { }#endif /* CONFIG_OPTPROBES */
kernel/kprobes.c +1 -1
@@ -652,7 +652,7 @@ void wait_for_kprobe_optimizer(void)mutex_unlock (&kprobe_mutex); } -static bool optprobe_queued_unopt (struct optimized_kprobe *op) +bool optprobe_queued_unopt (struct optimized_kprobe *op) {struct optimized_kprobe *_op;
Greg Kroah-Hartman
maintainerPATCH 362/529 x86/kprobes: Fix arch_check_optimized_kprobe check within optimized_kprobe range
In reply to Greg Kroah-HartmanFrom: Yang Jihong <[email protected]>
commit f1c97a1b4ef709e3f066f82e3ba3108c3b133ae6 upstream.
When arch_prepare_optimized_kprobe calculating jump destination address, it copies original instructions from jmp-optimized kprobe (see __recover_optprobed_insn), and calculated based on length of original instruction.
arch_check_optimized_kprobe does not check KPROBE_FLAG_OPTIMATED when checking whether jmp-optimized kprobe exists.
As a result, setup_detour_execution may jump to a range that has been overwritten by jump destination address, resulting in an inval opcode error.
For example, assume that register two kprobes whose addresses are <func+9> and <func+11> in "func" function.
The original code of "func" function is as follows:
0xffffffff816cb5e9 <+9>: push %r12 0xffffffff816cb5eb <+11>: xor %r12d,%r12d 0xffffffff816cb5ee <+14>: test %rdi,%rdi 0xffffffff816cb5f1 <+17>: setne %r12b 0xffffffff816cb5f5 <+21>: push %rbp
1.Register the kprobe for <func+11>, assume that is kp1, corresponding optimized_kprobe is op1.
After the optimization, "func" code changes to:
0xffffffff816cc079 <+9>: push %r12 0xffffffff816cc07b <+11>: jmp 0xffffffffa0210000 0xffffffff816cc080 <+16>: incl 0xf(%rcx) 0xffffffff816cc083 <+19>: xchg %eax,%ebp 0xffffffff816cc084 <+20>: (bad) 0xffffffff816cc085 <+21>: push %rbp
Now op1->flags == KPROBE_FLAG_OPTIMATED;
2. Register the kprobe for <func+9>, assume that is kp2, corresponding optimized_kprobe is op2.
register_kprobe(kp2)
register_aggr_kprobe
alloc_aggr_kprobe
__prepare_optimized_kprobe
arch_prepare_optimized_kprobe
__recover_optprobed_insn // copy original bytes from kp1->optinsn.copied_insn,
// jump address = <func+14>3. disable kp1:
disable_kprobe(kp1)
__disable_kprobe
...
if (p == orig_p || aggr_kprobe_disabled(orig_p)) {
ret = disarm_kprobe(orig_p, true) // add op1 in unoptimizing_list, not unoptimized
orig_p->flags |= KPROBE_FLAG_DISABLED; // op1->flags == KPROBE_FLAG_OPTIMATED | KPROBE_FLAG_DISABLED
...4. unregister kp2__unregister_kprobe_top
...
if (!kprobe_disabled(ap) && !kprobes_all_disarmed) {
optimize_kprobe(op)
...
if (arch_check_optimized_kprobe(op) < 0) // because op1 has KPROBE_FLAG_DISABLED, here not return
return;
p->kp.flags |= KPROBE_FLAG_OPTIMIZED; // now op2 has KPROBE_FLAG_OPTIMIZED}
"func" code now is:
0xffffffff816cc079 <+9>: int3 0xffffffff816cc07a <+10>: push %rsp 0xffffffff816cc07b <+11>: jmp 0xffffffffa0210000 0xffffffff816cc080 <+16>: incl 0xf(%rcx) 0xffffffff816cc083 <+19>: xchg %eax,%ebp 0xffffffff816cc084 <+20>: (bad) 0xffffffff816cc085 <+21>: push %rbp
5. if call "func", int3 handler call setup_detour_execution:
if (p->flags & KPROBE_FLAG_OPTIMIZED) {
...
regs->ip = (unsigned long)op->optinsn.insn + TMPL_END_IDX;
...
}The code for the destination address is
0xffffffffa021072c: push %r12 0xffffffffa021072e: xor %r12d,%r12d 0xffffffffa0210731: jmp 0xffffffff816cb5ee <func+14>
However, <func+14> is not a valid start instruction address. As a result, an error occurs.
--- arch/x86/kernel/kprobes/opt.c | 2 +- include/linux/kprobes.h | 1 + kernel/kprobes.c | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-)
arch/x86/kernel/kprobes/opt.c +1 -1
@@ -346,7 +346,7 @@ int arch_check_optimized_kprobe(struct ofor (i =1 ; i < op->optinsn.size; i++) { p =get_kprobe (op->kp.addr + i); -if (p && !kprobe_disabled (p)) +if (p && !kprobe_disarmed (p))return -EEXIST ; }
include/linux/kprobes.h +1 -0
@@ -343,6 +343,7 @@ extern int proc_kprobes_optimization_han#endif extern void wait_for_kprobe_optimizer (void );bool optprobe_queued_unopt (struct optimized_kprobe *op); +bool kprobe_disarmed (struct kprobe *p);#else static inline void wait_for_kprobe_optimizer (void ) { }#endif /* CONFIG_OPTPROBES */
kernel/kprobes.c +2 -2
@@ -447,8 +447,8 @@ static inline int kprobe_optready(structreturn 0 ; } -/* Return true(!0) if the kprobe is disarmed. Note: p must be on hash list */ -static inline int kprobe_disarmed (struct kprobe *p) +/* Return true if the kprobe is disarmed. Note: p must be on hash list */ +bool kprobe_disarmed (struct kprobe *p) {struct optimized_kprobe *op;
Greg Kroah-Hartman
maintainerPATCH 363/529 x86/microcode/amd: Remove load_microcode_amd()s bsp parameter
In reply to Greg Kroah-HartmanFrom: Borislav Petkov (AMD) <[email protected]>
commit 2355370cd941cbb20882cc3f34460f9f2b8f9a18 upstream.
It is always the BSP.
No functional changes.
--- arch/x86/kernel/cpu/microcode/amd.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-)
arch/x86/kernel/cpu/microcode/amd.c +5 -12
@@ -548,8 +548,7 @@ void load_ucode_amd_ap(unsigned int cpuiapply_microcode_early_amd (cpuid_1_eax, cp.data, cp.size, false); } -static enum ucode_state -load_microcode_amd (bool save,u8 family,const u8 *data,size_t size); +static enum ucode_state load_microcode_amd (u8 family,const u8 *data,size_t size);int __init save_microcode_in_initrd_amd (unsigned int cpuid_1_eax) {
@@ -567,7 +566,7 @@ int __init save_microcode_in_initrd_amd(if (!desc.mc)return -EINVAL ; - ret =load_microcode_amd (true,x86_family (cpuid_1_eax), desc.data, desc.size); + ret =load_microcode_amd (x86_family (cpuid_1_eax), desc.data, desc.size);if (ret >UCODE_UPDATED )return -EINVAL ;
@@ -845,8 +844,7 @@ static enum ucode_state __load_microcodereturn UCODE_OK ; } -static enum ucode_state -load_microcode_amd (bool save,u8 family,const u8 *data,size_t size) +static enum ucode_state load_microcode_amd (u8 family,const u8 *data,size_t size) {struct ucode_patch *p;enum ucode_state ret;
@@ -870,10 +868,6 @@ load_microcode_amd(bool save, u8 family, ret =UCODE_NEW ; } -/* save BSP's matching patch for early load */ -if (!save) -return ret; -memset (amd_ucode_patch,0 ,PATCH_MAX_SIZE );memcpy (amd_ucode_patch, p->data,min_t (u32, p->size,PATCH_MAX_SIZE ));
@@ -901,12 +895,11 @@ static enum ucode_state request_microcod {char fw_name[36 ] ="amd-ucode/microcode_amd.bin" ;struct cpuinfo_x86 *c = &cpu_data (cpu); -bool bsp = c->cpu_index == boot_cpu_data.cpu_index;enum ucode_state ret =UCODE_NFOUND ;const struct firmware *fw;/* reload ucode container only on the boot cpu */ -if (!refresh_fw || !bsp) +if (!refresh_fw)return UCODE_OK ;if (c->x86 >=0x15 )
@@ -921,7 +914,7 @@ static enum ucode_state request_microcodif (!verify_container (fw->data, fw->size, false)) goto fw_release; - ret =load_microcode_amd (bsp, c->x86, fw->data, fw->size); + ret =load_microcode_amd (c->x86, fw->data, fw->size); fw_release:release_firmware (fw);
Greg Kroah-Hartman
maintainerPATCH 364/529 x86/microcode/AMD: Add a @cpu parameter to the reloading functions
In reply to Greg Kroah-HartmanFrom: Borislav Petkov (AMD) <[email protected]>
commit a5ad92134bd153a9ccdcddf09a95b088f36c3cce upstream.
Will be used in a subsequent change.
--- arch/x86/include/asm/microcode.h | 4 ++-- arch/x86/include/asm/microcode_amd.h | 4 ++-- arch/x86/kernel/cpu/microcode/amd.c | 2 +- arch/x86/kernel/cpu/microcode/core.c | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-)
arch/x86/include/asm/microcode.h +2 -2
@@ -131,7 +131,7 @@ static inline unsigned int x86_cpuid_famint __init microcode_init (void );extern void __init load_ucode_bsp (void );extern void load_ucode_ap (void ); -void reload_early_microcode (void ); +void reload_early_microcode (unsigned int cpu);extern bool get_builtin_firmware (struct cpio_data *cd,const char *name);extern bool initrd_gone;void microcode_bsp_resume (void );
@@ -139,7 +139,7 @@ void microcode_bsp_resume(void);static inline int __init microcode_init (void ) {return 0 ; };static inline void __init load_ucode_bsp (void ) { }static inline void load_ucode_ap (void ) { } -static inline void reload_early_microcode (void ) { } +static inline void reload_early_microcode (unsigned int cpu) { }static inline void microcode_bsp_resume (void ) { }static inline bool get_builtin_firmware (struct cpio_data *cd,const char *name) {return false; }
arch/x86/include/asm/microcode_amd.h +2 -2
@@ -47,12 +47,12 @@ struct microcode_amd {extern void __init load_ucode_amd_bsp (unsigned int family);extern void load_ucode_amd_ap (unsigned int family);extern int __init save_microcode_in_initrd_amd (unsigned int family); -void reload_ucode_amd (void ); +void reload_ucode_amd (unsigned int cpu);#else static inline void __init load_ucode_amd_bsp (unsigned int family) {}static inline void load_ucode_amd_ap (unsigned int family) {}static inline int __init save_microcode_in_initrd_amd (unsigned int family) {return -EINVAL ; } -static inline void reload_ucode_amd (void ) {} +static inline void reload_ucode_amd (unsigned int cpu) {}#endif #endif /* _ASM_X86_MICROCODE_AMD_H */
arch/x86/kernel/cpu/microcode/amd.c +1 -1
@@ -573,7 +573,7 @@ int __init save_microcode_in_initrd_amd(return 0 ; } -void reload_ucode_amd (void ) +void reload_ucode_amd (unsigned int cpu) {struct microcode_amd *mc;u32 rev, dummy__always_unused ;
arch/x86/kernel/cpu/microcode/core.c +3 -3
@@ -315,7 +315,7 @@ struct cpio_data find_microcode_in_initr#endif } -void reload_early_microcode (void ) +void reload_early_microcode (unsigned int cpu) {int vendor, family;
@@ -329,7 +329,7 @@ void reload_early_microcode(void)break ;case X86_VENDOR_AMD :if (family >=0x10 ) -reload_ucode_amd (); +reload_ucode_amd (cpu);break ;default :break ;
@@ -707,7 +707,7 @@ void microcode_bsp_resume(void)if (uci->valid && uci->mc) microcode_ops->apply_microcode (cpu);else if (!uci->mc) -reload_early_microcode (); +reload_early_microcode (cpu); }static struct syscore_ops mc_syscore_ops = {
Greg Kroah-Hartman
maintainerPATCH 365/529 x86/microcode/AMD: Fix mixed steppings support
In reply to Greg Kroah-HartmanFrom: Borislav Petkov (AMD) <[email protected]>
commit 7ff6edf4fef38ab404ee7861f257e28eaaeed35f upstream.
The AMD side of the loader has always claimed to support mixed steppings. But somewhere along the way, it broke that by assuming that the cached patch blob is a single one instead of it being one per *node*.
So turn it into a per-node one so that each node can stash the blob relevant for it.
[ NB: Fixes tag is not really the exactly correct one but it is good
enough. ]
--- arch/x86/kernel/cpu/microcode/amd.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-)
arch/x86/kernel/cpu/microcode/amd.c +21 -13
@@ -55,7 +55,9 @@ struct cont_desc { };static u32 ucode_new_rev; -static u8 amd_ucode_patch[PATCH_MAX_SIZE ]; + +/* One blob per node. */ +static u8 amd_ucode_patch[MAX_NUMNODES ][PATCH_MAX_SIZE ];/* * Microcode patch container file is prepended to the initrd in cpio
@@ -429,7 +431,7 @@ apply_microcode_early_amd(u32 cpuid_1_ea patch = (u8 (*)[PATCH_MAX_SIZE ])__pa_nodebug (&amd_ucode_patch);#else new_rev = &ucode_new_rev; - patch = &amd_ucode_patch; + patch = &amd_ucode_patch[0 ];#endif desc.cpuid_1_eax = cpuid_1_eax;
@@ -575,10 +577,10 @@ int __init save_microcode_in_initrd_amd(void reload_ucode_amd (unsigned int cpu) { -struct microcode_amd *mc;u32 rev, dummy__always_unused ; +struct microcode_amd *mc; - mc = (struct microcode_amd *)amd_ucode_patch; + mc = (struct microcode_amd *)amd_ucode_patch[cpu_to_node (cpu)];rdmsr (MSR_AMD64_PATCH_LEVEL , rev, dummy);
@@ -846,6 +848,8 @@ static enum ucode_state __load_microcodestatic enum ucode_state load_microcode_amd (u8 family,const u8 *data,size_t size) { +struct cpuinfo_x86 *c; +unsigned int nid, cpu;struct ucode_patch *p;enum ucode_state ret;
@@ -858,18 +862,22 @@ static enum ucode_state load_microcode_areturn ret; } - p =find_patch (0 ); -if (!p) { -return ret; - }else { -if (boot_cpu_data.microcode >= p->patch_id) -return ret; +for_each_node (nid) { + cpu =cpumask_first (cpumask_of_node (nid)); + c = &cpu_data (cpu); + + p =find_patch (cpu); +if (!p) +continue ; + +if (c->microcode >= p->patch_id) +continue ; ret =UCODE_NEW ; - } -memset (amd_ucode_patch,0 ,PATCH_MAX_SIZE ); -memcpy (amd_ucode_patch, p->data,min_t (u32, p->size,PATCH_MAX_SIZE )); +memset (&amd_ucode_patch[nid],0 ,PATCH_MAX_SIZE ); +memcpy (&amd_ucode_patch[nid], p->data,min_t (u32, p->size,PATCH_MAX_SIZE )); + }return ret; }
Greg Kroah-Hartman
maintainerPATCH 366/529 x86/speculation: Allow enabling STIBP with legacy IBRS
In reply to Greg Kroah-HartmanFrom: KP Singh <[email protected]>
commit 6921ed9049bc7457f66c1596c5b78aec0dae4a9d upstream.
When plain IBRS is enabled (not enhanced IBRS), the logic in spectre_v2_user_select_mitigation() determines that STIBP is not needed.
The IBRS bit implicitly protects against cross-thread branch target injection. However, with legacy IBRS, the IBRS bit is cleared on returning to userspace for performance reasons which leaves userspace threads vulnerable to cross-thread branch target injection against which STIBP protects.
Exclude IBRS from the spectre_v2_in_ibrs_mode() check to allow for enabling STIBP (through seccomp/prctl() by default or always-on, if selected by spectre_v2_user kernel cmdline parameter).
[ bp: Massage. ]
--- arch/x86/kernel/cpu/bugs.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-)
arch/x86/kernel/cpu/bugs.c +18 -7
@@ -1066,14 +1066,18 @@ spectre_v2_parse_user_cmdline(void)return SPECTRE_V2_USER_CMD_AUTO ; } -static inline bool spectre_v2_in_ibrs_mode (enum spectre_v2_mitigation mode) +static inline bool spectre_v2_in_eibrs_mode (enum spectre_v2_mitigation mode) { -return mode ==SPECTRE_V2_IBRS || - mode ==SPECTRE_V2_EIBRS || +return mode ==SPECTRE_V2_EIBRS || mode ==SPECTRE_V2_EIBRS_RETPOLINE || mode ==SPECTRE_V2_EIBRS_LFENCE ; } +static inline bool spectre_v2_in_ibrs_mode (enum spectre_v2_mitigation mode) +{ +return spectre_v2_in_eibrs_mode (mode) || mode ==SPECTRE_V2_IBRS ; +} +static void __init spectre_v2_user_select_mitigation (void ) {
@@ -1136,12 +1140,19 @@ spectre_v2_user_select_mitigation(void) }/* -* If no STIBP, IBRS or enhanced IBRS is enabled, or SMT impossible, -* STIBP is not required. +* If no STIBP, enhanced IBRS is enabled, or SMT impossible, STIBP +* is not required. +* +* Enhanced IBRS also protects against cross-thread branch target +* injection in user-mode as the IBRS bit remains always set which +* implicitly enables cross-thread protections. However, in legacy IBRS +* mode, the IBRS bit is set only on kernel entry and cleared on return +* to userspace. This disables the implicit cross-thread protection, +* so allow for STIBP to be selected in that case. */ if (!boot_cpu_has (X86_FEATURE_STIBP ) || !smt_possible || -spectre_v2_in_ibrs_mode (spectre_v2_enabled)) +spectre_v2_in_eibrs_mode (spectre_v2_enabled))return ;/*
@@ -2235,7 +2246,7 @@ static ssize_t mmio_stale_data_show_statstatic char *stibp_state (void ) { -if (spectre_v2_in_ibrs_mode (spectre_v2_enabled)) +if (spectre_v2_in_eibrs_mode (spectre_v2_enabled))return "" ;switch (spectre_v2_user_stibp) {
Greg Kroah-Hartman
maintainerPATCH 367/529 Documentation/hw-vuln: Document the interaction between IBRS and STIBP
In reply to Greg Kroah-HartmanFrom: KP Singh <[email protected]>
commit e02b50ca442e88122e1302d4dbc1b71a4808c13f upstream.
Explain why STIBP is needed with legacy IBRS as currently implemented (KERNEL_IBRS) and why STIBP is not needed when enhanced IBRS is enabled.
--- Documentation/admin-guide/hw-vuln/spectre.rst | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-)
Documentation/admin-guide/hw-vuln/spectre.rst +16 -5
@@ -479,8 +479,16 @@ Spectre variant 2 On Intel Skylake-era systems the mitigation covers most, but not all, cases. See :ref:`[3] <spec_ref3>` for more details. - On CPUs with hardware mitigation for Spectre variant 2 (e.g. Enhanced - IBRS on x86), retpoline is automatically disabled at run time. + On CPUs with hardware mitigation for Spectre variant 2 (e.g. IBRS + or enhanced IBRS on x86), retpoline is automatically disabled at run time. + + Systems which support enhanced IBRS (eIBRS) enable IBRS protection once at + boot, by setting the IBRS bit, and they're automatically protected against + Spectre v2 variant attacks, including cross-thread branch target injections + on SMT systems (STIBP). In other words, eIBRS enables STIBP too. + + Legacy IBRS systems clear the IBRS bit on exit to userspace and + therefore explicitly enable STIBP for that The retpoline mitigation is turned on by default on vulnerable CPUs. It can be forced on or off by the administrator
@@ -504,9 +512,12 @@ Spectre variant 2 For Spectre variant 2 mitigation, individual user programs can be compiled with return trampolines for indirect branches. This protects them from consuming poisoned entries in the branch - target buffer left by malicious software. Alternatively, the - programs can disable their indirect branch speculation via prctl() - (See :ref:`Documentation/userspace-api/spec_ctrl.rst <set_spec_ctrl>`). + target buffer left by malicious software. + + On legacy IBRS systems, at return to userspace, implicit STIBP is disabled + because the kernel clears the IBRS bit. In this case, the userspace programs + can disable indirect branch speculation via prctl() (See + :ref:`Documentation/userspace-api/spec_ctrl.rst <set_spec_ctrl>`). On x86, this will turn on STIBP to guard against attacks from the sibling thread when the user program is running, and use IBPB to flush the branch target buffer when switching to/from the program.
Greg Kroah-Hartman
maintainerPATCH 368/529 brd: return 0/-error from brd_insert_page()
In reply to Greg Kroah-HartmanFrom: Jens Axboe <[email protected]>
commit db0ccc44a20b4bb3039c0f6885a1f9c3323c7673 upstream.
It currently returns a page, but callers just check for NULL/page to gauge success. Clean this up and return the appropriate error directly instead.
--- drivers/block/brd.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-)
drivers/block/brd.c +12 -14
@@ -80,11 +80,9 @@ static struct page *brd_lookup_page(stru }/* -* Look up and return a brd's page for a given sector. -* If one does not exist, allocate an empty page, and insert that. Then -* return it. +* Insert a new page for a given sector, if one does not already exist. */ -static struct page *brd_insert_page (struct brd_device *brd,sector_t sector) +static int brd_insert_page (struct brd_device *brd,sector_t sector) {pgoff_t idx;struct page *page;
@@ -92,7 +90,7 @@ static struct page *brd_insert_page(stru page =brd_lookup_page (brd, sector);if (page) -return page; +return 0 ;/* * Must use NOIO because we don't want to recurse back into the
@@ -101,11 +99,11 @@ static struct page *brd_insert_page(stru gfp_flags =GFP_NOIO | __GFP_ZERO | __GFP_HIGHMEM; page =alloc_page (gfp_flags);if (!page) -return NULL ; +return -ENOMEM ;if (radix_tree_preload (GFP_NOIO )) {__free_page (page); -return NULL ; +return -ENOMEM ; }spin_lock (&brd->brd_lock);
@@ -120,8 +118,7 @@ static struct page *brd_insert_page(struspin_unlock (&brd->brd_lock);radix_tree_preload_end (); - -return page; +return 0 ; }/*
@@ -174,16 +171,17 @@ static int copy_to_brd_setup(struct brd_ {unsigned int offset = (sector & (PAGE_SECTORS -1 )) <<SECTOR_SHIFT ;size_t copy; +int ret; copy =min_t (size_t, n,PAGE_SIZE - offset); -if (!brd_insert_page (brd, sector)) -return -ENOSPC ; + ret =brd_insert_page (brd, sector); +if (ret) +return ret;if (copy < n) { sector += copy >>SECTOR_SHIFT ; -if (!brd_insert_page (brd, sector)) -return -ENOSPC ; + ret =brd_insert_page (brd, sector); } -return 0 ; +return ret; }/*
Greg Kroah-Hartman
maintainerPATCH 369/529 ima: Align ima_file_mmap() parameters with mmap_file LSM hook
In reply to Greg Kroah-HartmanFrom: Roberto Sassu <[email protected]>
commit 4971c268b85e1c7a734a61622fc0813c86e2362e upstream.
Commit 98de59bfe4b2f ("take calculation of final prot in security_mmap_file() into a helper") moved the code to update prot, to be the actual protections applied to the kernel, to a new helper called mmap_prot().
However, while without the helper ima_file_mmap() was getting the updated prot, with the helper ima_file_mmap() gets the original prot, which contains the protections requested by the application.
A possible consequence of this change is that, if an application calls mmap() with only PROT_READ, and the kernel applies PROT_EXEC in addition, that application would have access to executable memory without having this event recorded in the IMA measurement list. This situation would occur for example if the application, before mmap(), calls the personality() system call with READ_IMPLIES_EXEC as the first argument.
Align ima_file_mmap() parameters with those of the mmap_file LSM hook, so that IMA can receive both the requested prot and the final prot. Since the requested protections are stored in a new variable, and the final protections are stored in the existing variable, this effectively restores the original behavior of the MMAP_CHECK hook.
--- include/linux/ima.h | 6 ++++-- security/integrity/ima/ima_main.c | 7 +++++-- security/security.c | 7 ++++--- 3 files changed, 13 insertions(+), 7 deletions(-)
include/linux/ima.h +4 -2
@@ -18,7 +18,8 @@ extern int ima_bprm_check(struct linux_bextern int ima_file_check (struct file *file,int mask);extern void ima_post_create_tmpfile (struct inode *inode);extern void ima_file_free (struct file *file); -extern int ima_file_mmap (struct file *file,unsigned long prot); +extern int ima_file_mmap (struct file *file,unsigned long reqprot, +unsigned long prot,unsigned long flags);extern int ima_file_mprotect (struct vm_area_struct *vma,unsigned long prot);extern int ima_load_data (enum kernel_load_data_id id,bool contents); extern int ima_post_load_data(char *buf, loff_t size,
@@ -70,7 +71,8 @@ static inline void ima_file_free(structreturn ; } -static inline int ima_file_mmap (struct file *file,unsigned long prot) +static inline int ima_file_mmap (struct file *file,unsigned long reqprot, +unsigned long prot,unsigned long flags) {return 0 ; }
security/integrity/ima/ima_main.c +5 -2
@@ -378,7 +378,9 @@ out:/** * ima_file_mmap - based on policy, collect/store measurement. * @file: pointer to the file to be measured (May be NULL) -* @prot: contains the protection that will be applied by the kernel. +* @reqprot: protection requested by the application +* @prot: protection that will be applied by the kernel +* @flags: operational flags * * Measure files being mmapped executable based on the ima_must_measure() * policy decision.
@@ -386,7 +388,8 @@ out:* On success return 0. On integrity appraisal error, assuming the file * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. */ -int ima_file_mmap (struct file *file,unsigned long prot) +int ima_file_mmap (struct file *file,unsigned long reqprot, +unsigned long prot,unsigned long flags) {u32 secid;
security/security.c +4 -3
@@ -1534,12 +1534,13 @@ static inline unsigned long mmap_prot(stint security_mmap_file (struct file *file,unsigned long prot,unsigned long flags) { +unsigned long prot_adj =mmap_prot (file, prot);int ret; - ret =call_int_hook (mmap_file,0 , file, prot, -mmap_prot (file, prot), flags); + + ret =call_int_hook (mmap_file,0 , file, prot, prot_adj, flags);if (ret)return ret; -return ima_file_mmap (file, prot); +return ima_file_mmap (file, prot, prot_adj, flags); }int security_mmap_addr (unsigned long addr)
Greg Kroah-Hartman
maintainerPATCH 370/529 irqdomain: Fix association race
In reply to Greg Kroah-HartmanFrom: Johan Hovold <[email protected]>
commit b06730a571a9ff1ba5bd6b20bf9e50e5a12f1ec6 upstream.
The sanity check for an already mapped virq is done outside of the irq_domain_mutex-protected section which means that an (unlikely) racing association may not be detected.
Fix this by factoring out the association implementation, which will also be used in a follow-on change to fix a shared-interrupt mapping race.
--- kernel/irq/irqdomain.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-)
kernel/irq/irqdomain.c +14 -5
@@ -516,8 +516,8 @@ void irq_domain_disassociate(struct irq_irq_domain_clear_mapping (domain, hwirq); } -int irq_domain_associate (struct irq_domain *domain,unsigned int virq, -irq_hw_number_t hwirq) +static int irq_domain_associate_locked (struct irq_domain *domain,unsigned int virq, +irq_hw_number_t hwirq) {struct irq_data *irq_data =irq_get_irq_data (virq);int ret;
@@ -530,7 +530,6 @@ int irq_domain_associate(struct irq_domaif (WARN (irq_data->domain,"error: virq%i is already associated" , virq))return -EINVAL ; -mutex_lock (&irq_domain_mutex); irq_data->hwirq = hwirq; irq_data->domain = domain;if (domain->ops->map) {
@@ -547,7 +546,6 @@ int irq_domain_associate(struct irq_doma } irq_data->domain =NULL ; irq_data->hwirq =0 ; -mutex_unlock (&irq_domain_mutex);return ret; }
@@ -558,12 +556,23 @@ int irq_domain_associate(struct irq_doma domain->mapcount++;irq_domain_set_mapping (domain, hwirq, irq_data); -mutex_unlock (&irq_domain_mutex);irq_clear_status_flags (virq,IRQ_NOREQUEST );return 0 ; } + +int irq_domain_associate (struct irq_domain *domain,unsigned int virq, +irq_hw_number_t hwirq) +{ +int ret; + +mutex_lock (&irq_domain_mutex); + ret =irq_domain_associate_locked (domain, virq, hwirq); +mutex_unlock (&irq_domain_mutex); + +return ret; +}EXPORT_SYMBOL_GPL (irq_domain_associate); void irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base,
Greg Kroah-Hartman
maintainerPATCH 371/529 irqdomain: Fix disassociation race
In reply to Greg Kroah-HartmanFrom: Johan Hovold <[email protected]>
commit 3f883c38f5628f46b30bccf090faec054088e262 upstream.
The global irq_domain_mutex is held when mapping interrupts from non-hierarchical domains but currently not when disposing them.
This specifically means that updates of the domain mapcount is racy (currently only used for statistics in debugfs).
Make sure to hold the global irq_domain_mutex also when disposing mappings from non-hierarchical domains.
--- kernel/irq/irqdomain.c | 5 +++++ 1 file changed, 5 insertions(+)
kernel/irq/irqdomain.c +5 -0
@@ -495,6 +495,9 @@ void irq_domain_disassociate(struct irq_return ; hwirq = irq_data->hwirq; + +mutex_lock (&irq_domain_mutex); +irq_set_status_flags (irq,IRQ_NOREQUEST );/* remove chip and handler */
@@ -514,6 +517,8 @@ void irq_domain_disassociate(struct irq_/* Clear reverse map for this hwirq */ irq_domain_clear_mapping (domain, hwirq); + +mutex_unlock (&irq_domain_mutex); } static int irq_domain_associate_locked(struct irq_domain *domain, unsigned int virq,
Greg Kroah-Hartman
maintainerPATCH 372/529 irqdomain: Drop bogus fwspec-mapping error handling
In reply to Greg Kroah-HartmanFrom: Johan Hovold <[email protected]>
commit e3b7ab025e931accdc2c12acf9b75c6197f1c062 upstream.
In case a newly allocated IRQ ever ends up not having any associated struct irq_data it would not even be possible to dispose the mapping.
Replace the bogus disposal with a WARN_ON().
This will also be used to fix a shared-interrupt mapping race, hence the CC-stable tag.
--- kernel/irq/irqdomain.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-)
kernel/irq/irqdomain.c +1 -6
@@ -837,13 +837,8 @@ unsigned int irq_create_fwspec_mapping(s } irq_data =irq_get_irq_data (virq); -if (!irq_data) { -if (irq_domain_is_hierarchy (domain)) -irq_domain_free_irqs (virq,1 ); -else -irq_dispose_mapping (virq); +if (WARN_ON (!irq_data))return 0 ; - }/* Store trigger type */ irqd_set_trigger_type (irq_data, type);
Greg Kroah-Hartman
maintainerPATCH 373/529 io_uring: handle TIF_NOTIFY_RESUME when checking for task_work
In reply to Greg Kroah-HartmanFrom: Jens Axboe <[email protected]>
commit b5d3ae202fbfe055aa2a8ae8524531ee1dcab717 upstream.
If TIF_NOTIFY_RESUME is set, then we need to call resume_user_mode_work() for PF_IO_WORKER threads. They never return to usermode, hence never get a chance to process any items that are marked by this flag. Most notably this includes the final put of files, but also any throttling markers set by block cgroups.
--- io_uring/io_uring.c | 7 +++++++ 1 file changed, 7 insertions(+)
io_uring/io_uring.c +7 -0
@@ -2460,6 +2460,13 @@ static inline unsigned int io_put_rw_kbustatic inline bool io_run_task_work (void ) { +/* +* PF_IO_WORKER never returns to userspace, so check here if we have +* notify work that needs processing. +*/ +if (current->flags &PF_IO_WORKER && +test_thread_flag (TIF_NOTIFY_RESUME )) +tracehook_notify_resume (NULL );if (test_thread_flag (TIF_NOTIFY_SIGNAL ) || current->task_works) {__set_current_state (TASK_RUNNING );tracehook_notify_signal ();
Greg Kroah-Hartman
maintainerPATCH 374/529 io_uring: mark task TASK_RUNNING before handling resume/task work
In reply to Greg Kroah-HartmanFrom: Jens Axboe <[email protected]>
commit 2f2bb1ffc9983e227424d0787289da5483b0c74f upstream.
Just like for task_work, set the task mode to TASK_RUNNING before doing potential resume work. We're not holding any locks at this point, but we may have already set the task state to TASK_INTERRUPTIBLE in preparation for going to sleep waiting for events. Ensure that we set it back to TASK_RUNNING if we have work to process, to avoid warnings on calling blocking operations with !TASK_RUNNING.
--- io_uring/io_uring.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
io_uring/io_uring.c +3 -1
@@ -2465,8 +2465,10 @@ static inline bool io_run_task_work(void* notify work that needs processing. */ if (current->flags &PF_IO_WORKER && -test_thread_flag (TIF_NOTIFY_RESUME )) +test_thread_flag (TIF_NOTIFY_RESUME )) { +__set_current_state (TASK_RUNNING );tracehook_notify_resume (NULL ); + }if (test_thread_flag (TIF_NOTIFY_SIGNAL ) || current->task_works) {__set_current_state (TASK_RUNNING );tracehook_notify_signal ();
Greg Kroah-Hartman
maintainerPATCH 375/529 io_uring: add a conditional reschedule to the IOPOLL cancelation loop
In reply to Greg Kroah-HartmanFrom: Jens Axboe <[email protected]>
commit fcc926bb857949dbfa51a7d95f3f5ebc657f198c upstream.
If the kernel is configured with CONFIG_PREEMPT_NONE, we could be sitting in a tight loop reaping events but not giving them a chance to finish. This results in a trace ala:
rcu: INFO: rcu_sched self-detected stall on CPU
rcu: 2-...!: (5249 ticks this GP) idle=935c/1/0x4000000000000000 softirq=4265/4274 fqs=1
(t=5251 jiffies g=465 q=4135 ncpus=4)rcu: rcu_sched kthread starved for 5249 jiffies! g465 f0x0 RCU_GP_WAIT_FQS(5) ->state=0x0 ->cpu=0
rcu: Unless rcu_sched kthread gets sufficient CPU time, OOM is now expected behavior.
rcu: RCU grace-period kthread stack dump:
task:rcu_sched state:R running task stack:0 pid:12 ppid:2 flags:0x00000008
Call trace: __switch_to+0xb0/0xc8 __schedule+0x43c/0x520 schedule+0x4c/0x98 schedule_timeout+0xbc/0xdc rcu_gp_fqs_loop+0x308/0x344 rcu_gp_kthread+0xd8/0xf0 kthread+0xb8/0xc8 ret_from_fork+0x10/0x20 rcu: Stack dump where RCU GP kthread last ran: Task dump for CPU 0: task:kworker/u8:10 state:R running task stack:0 pid:89 ppid:2 flags:0x0000000a Workqueue: events_unbound io_ring_exit_work Call trace: __switch_to+0xb0/0xc8 0xffff0000c8fefd28 CPU: 2 PID: 95 Comm: kworker/u8:13 Not tainted 6.2.0-rc5-00042-g40316e337c80-dirty #2759 Hardware name: linux,dummy-virt (DT) Workqueue: events_unbound io_ring_exit_work pstate: 61400005 (nZCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--) pc : io_do_iopoll+0x344/0x360 lr : io_do_iopoll+0xb8/0x360
sp : ffff800009bebc60
x29: ffff800009bebc60 x28: 0000000000000000 x27: 0000000000000000
x26: ffff0000c0f67d48 x25: ffff0000c0f67840 x24: ffff800008950024
x23: 0000000000000001 x22: 0000000000000000 x21: ffff0000c27d3200
x20: ffff0000c0f67840 x19: ffff0000c0f67800 x18: 0000000000000000
x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000
x14: 0000000000000001 x13: 0000000000000001 x12: 0000000000000000
x11: 0000000000000179 x10: 0000000000000870 x9 : ffff800009bebd60 x8 : ffff0000c27d3ad0 x7 : fefefefefefefeff x6 : 0000646e756f626e x5 : ffff0000c0f67840 x4 : 0000000000000000 x3 : ffff0000c2398000 x2 : 0000000000000000 x1 : 0000000000000000 x0 : 0000000000000000
Call trace: io_do_iopoll+0x344/0x360 io_uring_try_cancel_requests+0x21c/0x334 io_ring_exit_work+0x90/0x40c process_one_work+0x1a4/0x254 worker_thread+0x1ec/0x258 kthread+0xb8/0xc8 ret_from_fork+0x10/0x20
Add a cond_resched() in the cancelation IOPOLL loop to fix this.
--- io_uring/io_uring.c | 1 + 1 file changed, 1 insertion(+)
io_uring/io_uring.c +1 -0
@@ -9690,6 +9690,7 @@ static void io_uring_try_cancel_requestswhile (!list_empty_careful (&ctx->iopoll_list)) {io_iopoll_try_reap_events (ctx); ret = true; +cond_resched (); } }
Greg Kroah-Hartman
maintainerPATCH 376/529 io_uring/rsrc: disallow multi-source reg buffers
In reply to Greg Kroah-HartmanFrom: Pavel Begunkov <[email protected]>
commit edd478269640b360c6f301f2baa04abdda563ef3 upstream.
If two or more mappings go back to back to each other they can be passed into io_uring to be registered as a single registered buffer. That would even work if mappings came from different sources, e.g. it's possible to mix in this way anon pages and pages from shmem or hugetlb. That is not a problem but it'd rather be less prone if we forbid such mixing.
--- io_uring/io_uring.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
io_uring/io_uring.c +8 -5
@@ -9057,14 +9057,17 @@ static int io_sqe_buffer_register(struct pret =pin_user_pages (ubuf, nr_pages,FOLL_WRITE |FOLL_LONGTERM , pages, vmas);if (pret == nr_pages) { +struct file *file = vmas[0 ]->vm_file; +/* don't support file backed memory */ for (i =0 ; i < nr_pages; i++) { -struct vm_area_struct *vma = vmas[i]; - -if (vma_is_shmem (vma)) +if (vmas[i]->vm_file != file) { + ret = -EINVAL ; +break ; + } +if (!file)continue ; -if (vma->vm_file && - !is_file_hugepages (vma->vm_file)) { +if (!vma_is_shmem (vmas[i]) && !is_file_hugepages (file)) { ret = -EOPNOTSUPP ;break ; }
Greg Kroah-Hartman
maintainerPATCH 377/529 io_uring: remove MSG_NOSIGNAL from recvmsg
In reply to Greg Kroah-HartmanFrom: David Lamparter <[email protected]>
commit 7605c43d67face310b4b87dee1a28bc0c8cd8c0f upstream.
MSG_NOSIGNAL is not applicable for the receiving side, SIGPIPE is generated when trying to write to a "broken pipe". AF_PACKET's packet_recvmsg() does enforce this, giving back EINVAL when MSG_NOSIGNAL is set - making it unuseable in io_uring's recvmsg.
Remove MSG_NOSIGNAL from io_recvmsg_prep().
--- io_uring/io_uring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
io_uring/io_uring.c +1 -1
@@ -4995,7 +4995,7 @@ static int io_recvmsg_prep(struct io_kio sr->umsg =u64_to_user_ptr (READ_ONCE (sqe->addr)); sr->len =READ_ONCE (sqe->len); sr->bgid =READ_ONCE (sqe->buf_group); - sr->msg_flags =READ_ONCE (sqe->msg_flags) |MSG_NOSIGNAL ; + sr->msg_flags =READ_ONCE (sqe->msg_flags);if (sr->msg_flags &MSG_DONTWAIT ) req->flags |=REQ_F_NOWAIT ;
Greg Kroah-Hartman
maintainerPATCH 378/529 io_uring/poll: allow some retries for poll triggering spuriously
In reply to Greg Kroah-HartmanFrom: Jens Axboe <[email protected]>
commit c16bda37594f83147b167d381d54c010024efecf upstream.
If we get woken spuriously when polling and fail the operation with -EAGAIN again, then we generally only allow polling again if data had been transferred at some point. This is indicated with REQ_F_PARTIAL_IO. However, if the spurious poll triggers when the socket was originally empty, then we haven't transferred data yet and we will fail the poll re-arm. This either punts the socket to io-wq if it's blocking, or it fails the request with -EAGAIN if not. Neither condition is desirable, as the former will slow things down, while the latter will make the application confused.
We want to ensure that a repeated poll trigger doesn't lead to infinite work making no progress, that's what the REQ_F_PARTIAL_IO check was for. But it doesn't protect against a loop post the first receive, and it's unnecessarily strict if we started out with an empty socket.
Add a somewhat random retry count, just to put an upper limit on the potential number of retries that will be done. This should be high enough that we won't really hit it in practice, unless something needs to be aborted anyway.
--- io_uring/io_uring.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
io_uring/io_uring.c +14 -2
@@ -486,6 +486,7 @@ struct io_poll_iocb {struct file *file;struct wait_queue_head *head;__poll_t events; +int retries;struct wait_queue_entry wait; };
@@ -5749,6 +5750,14 @@ enum { IO_APOLL_READY }; +/* +* We can't reliably detect loops in repeated poll triggers and issue +* subsequently failing. But rather than fail these immediately, allow a +* certain amount of retries before we give up. Given that this condition +* should _rarely_ trigger even once, we should be fine with a larger value. +*/ +#define APOLL_MAX_RETRY 128 +static int io_arm_poll_handler (struct io_kiocb *req) {const struct io_op_def *def = &io_op_defs[req->opcode];
@@ -5760,8 +5769,6 @@ static int io_arm_poll_handler(struct ioif (!req->file || !file_can_poll (req->file))return IO_APOLL_ABORTED ; -if ((req->flags & (REQ_F_POLLED |REQ_F_PARTIAL_IO )) ==REQ_F_POLLED ) -return IO_APOLL_ABORTED ;if (!def->pollin && !def->pollout)return IO_APOLL_ABORTED ;
@@ -5779,8 +5786,13 @@ static int io_arm_poll_handler(struct ioif (req->flags &REQ_F_POLLED ) { apoll = req->apoll;kfree (apoll->double_poll); +if (unlikely (!--apoll->poll.retries)) { + apoll->double_poll =NULL ; +return IO_APOLL_ABORTED ; + } }else { apoll =kmalloc (sizeof (*apoll),GFP_ATOMIC ); + apoll->poll.retries =APOLL_MAX_RETRY ; }if (unlikely (!apoll))return IO_APOLL_ABORTED ;
Greg Kroah-Hartman
maintainerPATCH 379/529 ALSA: ice1712: Do not left ice->gpio_mutex locked in aureon_add_controls()
In reply to Greg Kroah-HartmanFrom: Dmitry Fomin <[email protected]>
commit 951606a14a8901e3551fe4d8d3cedd73fe954ce1 upstream.
If snd_ctl_add() fails in aureon_add_controls(), it immediately returns and leaves ice->gpio_mutex locked. ice->gpio_mutex locks in snd_ice1712_save_gpio_status and unlocks in snd_ice1712_restore_gpio_status(ice).
It seems that the mutex is required only for aureon_cs8415_get(), so snd_ice1712_restore_gpio_status(ice) can be placed just after that. Compile tested only.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- sound/pci/ice1712/aureon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/pci/ice1712/aureon.c +1 -1
@@ -1892,6 +1892,7 @@ static int aureon_add_controls(struct snunsigned char id;snd_ice1712_save_gpio_status (ice); id =aureon_cs8415_get (ice,CS8415_ID ); +snd_ice1712_restore_gpio_status (ice);if (id !=0x41 )dev_info (ice->card->dev,"No CS8415 chip. Skipping CS8415 controls.\n" );
@@ -1909,7 +1910,6 @@ static int aureon_add_controls(struct sn kctl->id.device = ice->pcm->device; } } -snd_ice1712_restore_gpio_status (ice); }return 0 ;
Greg Kroah-Hartman
maintainerPATCH 380/529 ALSA: hda/realtek: Add quirk for HP EliteDesk 800 G6 Tower PC
In reply to Greg Kroah-HartmanFrom: Łukasz Stelmach <[email protected]>
commit ea24b9953bcd3889f77a66e7f1d7e86e995dd9c3 upstream.
HP EliteDesk 800 G6 Tower PC (103c:870c) requires a quirk for enabling headset-mic.
--- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+)
sound/pci/hda/patch_realtek.c +1 -0
@@ -11153,6 +11153,7 @@ static const struct snd_pci_quirk alc662SND_PCI_QUIRK (0x1028 ,0x0698 ,"Dell" ,ALC668_FIXUP_DELL_MIC_NO_PRESENCE ),SND_PCI_QUIRK (0x1028 ,0x069f ,"Dell" ,ALC668_FIXUP_DELL_MIC_NO_PRESENCE ),SND_PCI_QUIRK (0x103c ,0x1632 ,"HP RP5800" ,ALC662_FIXUP_HP_RP5800 ), +SND_PCI_QUIRK (0x103c ,0x870c ,"HP" ,ALC897_FIXUP_HP_HSMIC_VERB ),SND_PCI_QUIRK (0x103c ,0x8719 ,"HP" ,ALC897_FIXUP_HP_HSMIC_VERB ),SND_PCI_QUIRK (0x103c ,0x873e ,"HP" ,ALC671_FIXUP_HP_HEADSET_MIC2 ), SND_PCI_QUIRK(0x103c, 0x877e, "HP 288 Pro G6", ALC671_FIXUP_HP_HEADSET_MIC2),
Greg Kroah-Hartman
maintainerPATCH 381/529 jbd2: fix data missing when reusing bh which is ready to be checkpointed
In reply to Greg Kroah-HartmanFrom: Zhihao Cheng <[email protected]>
commit e6b9bd7290d334451ce054e98e752abc055e0034 upstream.
Following process will make data lost and could lead to a filesystem corrupted problem:
1. jh(bh) is inserted into T1->t_checkpoint_list, bh is dirty, and jh->b_transaction = NULL
2. T1 is added into journal->j_checkpoint_transactions.
3. Get bh prepare to write while doing checkpoing:
PA PB
do_get_write_access jbd2_log_do_checkpoint
spin_lock(&jh->b_state_lock)
if (buffer_dirty(bh))
clear_buffer_dirty(bh) // clear buffer dirty
set_buffer_jbddirty(bh)
transaction =
journal->j_checkpoint_transactions
jh = transaction->t_checkpoint_list
if (!buffer_dirty(bh))
__jbd2_journal_remove_checkpoint(jh)
// bh won't be flushed
jbd2_cleanup_journal_tail
__jbd2_journal_file_buffer(jh, transaction, BJ_Reserved)4. Aborting journal/Power-cut before writing latest bh on journal area.
In this way we get a corrupted filesystem with bh's data lost.
Fix it by moving the clearing of buffer_dirty bit just before the call to __jbd2_journal_file_buffer(), both bit clearing and jh->b_transaction assignment are under journal->j_list_lock locked, so that jbd2_log_do_checkpoint() will wait until jh's new transaction fininshed even bh is currently not dirty. And journal_shrink_one_cp_list() won't remove jh from checkpoint list if the buffer head is reused in do_get_write_access().
Fetch a reproducer in [Link].
--- fs/jbd2/transaction.c | 50 +++++++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 21 deletions(-)
fs/jbd2/transaction.c +29 -21
@@ -984,36 +984,28 @@ repeat:* ie. locked but not dirty) or tune2fs (which may actually have * the buffer dirtied, ugh.) */ -if (buffer_dirty (bh)) { +if (buffer_dirty (bh) && jh->b_transaction) { +warn_dirty_buffer (bh);/* -* First question: is this buffer already part of the current -* transaction or the existing committing transaction? -*/ -if (jh->b_transaction) { -J_ASSERT_JH (jh, - jh->b_transaction == transaction || - jh->b_transaction == - journal->j_committing_transaction); -if (jh->b_next_transaction) -J_ASSERT_JH (jh, jh->b_next_transaction == - transaction); -warn_dirty_buffer (bh); - } -/* -* In any case we need to clean the dirty flag and we must -* do it under the buffer lock to be sure we don't race -* with running write-out. +* We need to clean the dirty flag and we must do it under the +* buffer lock to be sure we don't race with running write-out. */ JBUFFER_TRACE (jh,"Journalling dirty buffer" );clear_buffer_dirty (bh); +/* +* The buffer is going to be added to BJ_Reserved list now and +* nothing guarantees jbd2_journal_dirty_metadata() will be +* ever called for it. So we need to set jbddirty bit here to +* make sure the buffer is dirtied and written out when the +* journaling machinery is done with it. +*/ set_buffer_jbddirty (bh); } -unlock_buffer (bh); - error = -EROFS ;if (is_handle_aborted (handle)) {spin_unlock (&jh->b_state_lock); +unlock_buffer (bh); goto out; } error =0 ;
@@ -1023,8 +1015,10 @@ repeat:* b_next_transaction points to it */ if (jh->b_transaction == transaction || - jh->b_next_transaction == transaction) + jh->b_next_transaction == transaction) { +unlock_buffer (bh); goto done; + }/* * this is the first time this transaction is touching this buffer,
@@ -1048,10 +1042,24 @@ repeat:*/ smp_wmb ();spin_lock (&journal->j_list_lock); +if (test_clear_buffer_dirty (bh)) { +/* +* Execute buffer dirty clearing and jh->b_transaction +* assignment under journal->j_list_lock locked to +* prevent bh being removed from checkpoint list if +* the buffer is in an intermediate state (not dirty +* and jh->b_transaction is NULL). +*/ +JBUFFER_TRACE (jh,"Journalling dirty buffer" ); +set_buffer_jbddirty (bh); + }__jbd2_journal_file_buffer (jh, transaction, BJ_Reserved);spin_unlock (&journal->j_list_lock); +unlock_buffer (bh); goto done; } +unlock_buffer (bh); +/* * If there is already a copy-out version of this buffer, then we don't * need to make another one
Greg Kroah-Hartman
maintainerPATCH 382/529 ext4: optimize ea_inode block expansion
In reply to Greg Kroah-HartmanFrom: Jun Nie <[email protected]>
commit 1e9d62d252812575ded7c620d8fc67c32ff06c16 upstream.
Copy ea data from inode entry when expanding ea block if possible. Then remove the ea entry if expansion success. Thus memcpy to a temporary buffer may be avoided.
If the expansion fails, we do not need to recovery the removed ea entry neither in this way.
--- fs/ext4/xattr.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-)
fs/ext4/xattr.c +17 -11
@@ -2564,9 +2564,8 @@ static int ext4_xattr_move_to_block(hand is =kzalloc (sizeof (struct ext4_xattr_ibody_find ),GFP_NOFS ); bs =kzalloc (sizeof (struct ext4_xattr_block_find ),GFP_NOFS ); - buffer =kvmalloc (value_size,GFP_NOFS ); b_entry_name =kmalloc (entry->e_name_len +1 ,GFP_NOFS ); -if (!is || !bs || !buffer || !b_entry_name) { +if (!is || !bs || !b_entry_name) { error = -ENOMEM ; goto out; }
@@ -2578,12 +2577,18 @@ static int ext4_xattr_move_to_block(hand/* Save the entry name and the entry value */ if (entry->e_value_inum) { + buffer =kvmalloc (value_size,GFP_NOFS ); +if (!buffer) { + error = -ENOMEM ; + goto out; + } + error =ext4_xattr_inode_get (inode, entry, buffer, value_size);if (error) goto out; }else {size_t value_offs =le16_to_cpu (entry->e_value_offs); -memcpy (buffer, (void *)IFIRST (header) + value_offs, value_size); + buffer = (void *)IFIRST (header) + value_offs; }memcpy (b_entry_name, entry->e_name, entry->e_name_len);
@@ -2598,25 +2603,26 @@ static int ext4_xattr_move_to_block(handif (error) goto out; -/* Remove the chosen entry from the inode */ - error =ext4_xattr_ibody_set (handle, inode, &i, is); -if (error) - goto out; - i.value = buffer; i.value_len = value_size; error =ext4_xattr_block_find (inode, &i, bs);if (error) goto out; -/* Add entry which was removed from the inode into the block */ +/* Move ea entry from the inode into the block */ error =ext4_xattr_block_set (handle, inode, &i, bs);if (error) goto out; - error =0 ; + +/* Remove the chosen entry from the inode */ + i.value =NULL ; + i.value_len =0 ; + error =ext4_xattr_ibody_set (handle, inode, &i, is); + out:kfree (b_entry_name); -kvfree (buffer); +if (entry->e_value_inum && buffer) +kvfree (buffer);if (is)brelse (is->iloc.bh);if (bs)
Greg Kroah-Hartman
maintainerPATCH 383/529 ext4: refuse to create ea block when umounted
In reply to Greg Kroah-HartmanFrom: Jun Nie <[email protected]>
commit f31173c19901a96bb2ebf6bcfec8a08df7095c91 upstream.
The ea block expansion need to access s_root while it is already set as NULL when umount is triggered. Refuse this request to avoid panic.
--- fs/ext4/xattr.c | 7 +++++++ 1 file changed, 7 insertions(+)
fs/ext4/xattr.c +7 -0
@@ -1415,6 +1415,13 @@ static struct inode *ext4_xattr_inode_cruid_t owner[2 ] = {i_uid_read (inode),i_gid_read (inode) };int err; +if (inode->i_sb->s_root ==NULL ) { +ext4_warning (inode->i_sb, +"refuse to create EA inode when umounting" ); +WARN_ON (1 ); +return ERR_PTR (-EINVAL ); + } +/* * Let the next inode be the goal, so we try and allocate the EA inode * in the same group, or nearby one.
Greg Kroah-Hartman
maintainerPATCH 384/529 mtd: spi-nor: Fix shift-out-of-bounds in spi_nor_set_erase_type
In reply to Greg Kroah-HartmanFrom: Louis Rannou <[email protected]>
commit f0f0cfdc3a024e21161714f2e05f0df3b84d42ad upstream.
spi_nor_set_erase_type() was used either to set or to mask out an erase type. When we used it to mask out an erase type a shift-out-of-bounds was hit:
UBSAN: shift-out-of-bounds in drivers/mtd/spi-nor/core.c:2237:24
shift exponent 4294967295 is too large for 32-bit type 'int'
The setting of the size_{shift, mask} and of the opcode are unnecessary when the erase size is zero, as throughout the code just the erase size is considered to determine whether an erase type is supported or not. Setting the opcode to 0xFF was wrong too as nobody guarantees that 0xFF is an unused opcode. Thus when masking out an erase type, just set the erase size to zero. This will fix the shift-out-of-bounds.
--- drivers/mtd/spi-nor/core.c | 9 +++++++++ drivers/mtd/spi-nor/core.h | 1 + drivers/mtd/spi-nor/sfdp.c | 4 ++-- 3 files changed, 12 insertions(+), 2 deletions(-)
drivers/mtd/spi-nor/core.c +9 -0
@@ -2425,6 +2425,15 @@ void spi_nor_set_erase_type(struct spi_n }/** +* spi_nor_mask_erase_type() - mask out a SPI NOR erase type +* @erase: pointer to a structure that describes a SPI NOR erase type +*/ +void spi_nor_mask_erase_type (struct spi_nor_erase_type *erase) +{ + erase->size =0 ; +} + +/** * spi_nor_init_uniform_erase_map() - Initialize uniform erase map * @map: the erase map of the SPI NOR * @erase_mask: bitmask encoding erase types that can erase the entire
drivers/mtd/spi-nor/core.h +1 -0
@@ -424,6 +424,7 @@ void spi_nor_set_pp_settings(struct spi_void spi_nor_set_erase_type (struct spi_nor_erase_type *erase,u32 size,u8 opcode); +void spi_nor_mask_erase_type (struct spi_nor_erase_type *erase);struct spi_nor_erase_region *spi_nor_region_next (struct spi_nor_erase_region *region); void spi_nor_init_uniform_erase_map(struct spi_nor_erase_map *map,
drivers/mtd/spi-nor/sfdp.c +2 -2
@@ -852,7 +852,7 @@ spi_nor_init_non_uniform_erase_map(struc*/ for (i =0 ; i <SNOR_ERASE_TYPE_MAX ; i++)if (!(regions_erase_type &BIT (erase[i].idx))) -spi_nor_set_erase_type (&erase[i],0 ,0xFF ); +spi_nor_mask_erase_type (&erase[i]);return 0 ; }
@@ -1063,7 +1063,7 @@ static int spi_nor_parse_4bait(struct sp erase_type[i].opcode = (dwords[1 ] >> erase_type[i].idx *8 ) &0xFF ; else - spi_nor_set_erase_type(&erase_type[i], 0u, 0xFF); + spi_nor_mask_erase_type(&erase_type[i]); }/*
Greg Kroah-Hartman
maintainerPATCH 385/529 dm: add cond_resched() to dm_wq_work()
In reply to Greg Kroah-HartmanFrom: Pingfan Liu <[email protected]>
commit 0ca44fcef241768fd25ee763b3d203b9852f269b upstream.
Otherwise the while() loop in dm_wq_work() can result in a "dead loop" on systems that have preemption disabled. This is particularly problematic on single cpu systems.
--- drivers/md/dm.c | 1 + 1 file changed, 1 insertion(+)
drivers/md/dm.c +1 -0
@@ -2393,6 +2393,7 @@ static void dm_wq_work(struct work_strucbreak ;submit_bio_noacct (bio); +cond_resched (); } }
Greg Kroah-Hartman
maintainerPATCH 386/529 wifi: rtl8xxxu: Use a longer retry limit of 48
In reply to Greg Kroah-HartmanFrom: Bitterblue Smith <[email protected]>
commit 2a86aa9a1892d60ef2e3f310f5b42b8b05546d65 upstream.
The Realtek rate control algorithm goes back and forth a lot between the highest and the lowest rate it's allowed to use. This is due to a lot of frames being dropped because the retry limits set by IEEE80211_CONF_CHANGE_RETRY_LIMITS are too low. (Experimentally, they are 4 for long frames and 7 for short frames.)
The vendor drivers hardcode the value 48 for both retry limits (for station mode), which makes dropped frames very rare and thus the rate control is more stable.
Because most Realtek chips handle the rate control in the firmware, which can't be modified, ignore the limits set by IEEE80211_CONF_CHANGE_RETRY_LIMITS and use the value 48 (set during chip initialisation), same as the vendor drivers.
--- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 9 --------- 1 file changed, 9 deletions(-)
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +0 -9
@@ -5908,7 +5908,6 @@ static int rtl8xxxu_config(struct ieee80 {struct rtl8xxxu_priv *priv = hw->priv;struct device *dev = &priv->udev->dev; -u16 val16;int ret =0 , channel;bool ht40;
@@ -5918,14 +5917,6 @@ static int rtl8xxxu_config(struct ieee80 __func__, hw->conf.chandef.chan->hw_value, changed, hw->conf.chandef.width); -if (changed &IEEE80211_CONF_CHANGE_RETRY_LIMITS ) { - val16 = ((hw->conf.long_frame_max_tx_count << -RETRY_LIMIT_LONG_SHIFT ) &RETRY_LIMIT_LONG_MASK ) | - ((hw->conf.short_frame_max_tx_count << -RETRY_LIMIT_SHORT_SHIFT ) &RETRY_LIMIT_SHORT_MASK ); -rtl8xxxu_write16 (priv,REG_RETRY_LIMIT , val16); - } -if (changed &IEEE80211_CONF_CHANGE_CHANNEL ) {switch (hw->conf.chandef.width) {case NL80211_CHAN_WIDTH_20_NOHT :
Greg Kroah-Hartman
maintainerPATCH 387/529 wifi: cfg80211: Fix use after free for wext
In reply to Greg Kroah-HartmanFrom: Alexander Wetzel <[email protected]>
commit 015b8cc5e7c4d7bb671f1984d7b7338c310b185b upstream.
Key information in wext.connect is not reset on (re)connect and can hold data from a previous connection.
Reset key data to avoid that drivers or mac80211 incorrectly detect a WEP connection request and access the freed or already reused memory.
Additionally optimize cfg80211_sme_connect() and avoid an useless schedule of conn_work.
--- net/wireless/sme.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-)
net/wireless/sme.c +26 -5
@@ -269,6 +269,15 @@ void cfg80211_conn_work(struct work_strurtnl_unlock (); } +static void cfg80211_step_auth_next (struct cfg80211_conn *conn, +struct cfg80211_bss *bss) +{ +memcpy (conn->bssid, bss->bssid,ETH_ALEN ); + conn->params.bssid = conn->bssid; + conn->params.channel = bss->channel; + conn->state =CFG80211_CONN_AUTHENTICATE_NEXT ; +} +/* Returned bss is reference counted and must be cleaned up appropriately. */ static struct cfg80211_bss *cfg80211_get_conn_bss (struct wireless_dev *wdev) {
@@ -286,10 +295,7 @@ static struct cfg80211_bss *cfg80211_getif (!bss)return NULL ; -memcpy (wdev->conn->bssid, bss->bssid,ETH_ALEN ); - wdev->conn->params.bssid = wdev->conn->bssid; - wdev->conn->params.channel = bss->channel; - wdev->conn->state =CFG80211_CONN_AUTHENTICATE_NEXT ; +cfg80211_step_auth_next (wdev->conn, bss);schedule_work (&rdev->conn_work);return bss;
@@ -568,7 +574,12 @@ static int cfg80211_sme_connect(struct w wdev->conn->params.ssid_len = wdev->ssid_len;/* see if we have the bss already */ - bss =cfg80211_get_conn_bss (wdev); + bss =cfg80211_get_bss (wdev->wiphy, wdev->conn->params.channel, + wdev->conn->params.bssid, + wdev->conn->params.ssid, + wdev->conn->params.ssid_len, + wdev->conn_bss_type, +IEEE80211_PRIVACY (wdev->conn->params.privacy));if (prev_bssid) {memcpy (wdev->conn->prev_bssid, prev_bssid,ETH_ALEN );
@@ -579,6 +590,7 @@ static int cfg80211_sme_connect(struct wif (bss) {enum nl80211_timeout_reason treason; +cfg80211_step_auth_next (wdev->conn, bss); err =cfg80211_conn_do_work (wdev, &treason);cfg80211_put_bss (wdev->wiphy, bss); }else {
@@ -1245,6 +1257,15 @@ int cfg80211_connect(struct cfg80211_reg }else {if (WARN_ON (connkeys))return -EINVAL ; + +/* connect can point to wdev->wext.connect which +* can hold key data from a previous connection +*/ + connect->key =NULL ; + connect->key_len =0 ; + connect->key_idx =0 ; + connect->crypto.cipher_group =0 ; + connect->crypto.n_ciphers_pairwise =0 ; } wdev->connect_keys = connkeys;
Greg Kroah-Hartman
maintainerPATCH 388/529 thermal: intel: powerclamp: Fix cur_state for multi package system
In reply to Greg Kroah-HartmanFrom: Srinivas Pandruvada <[email protected]>
commit 8e47363588377e1bdb65e2b020b409cfb44dd260 upstream.
The powerclamp cooling device cur_state shows actual idle observed by package C-state idle counters. But the implementation is not sufficient for multi package or multi die system. The cur_state value is incorrect. On these systems, these counters must be read from each package/die and somehow aggregate them. But there is no good method for aggregation.
It was not a problem when explicit CPU model addition was required to enable intel powerclamp. In this way certain CPU models could have been avoided. But with the removal of CPU model check with the availability of Package C-state counters, the driver is loaded on most of the recent systems.
For multi package/die systems, just show the actual target idle state, the system is trying to achieve. In powerclamp this is the user set state minus one.
Also there is no use of starting a worker thread for polling package C-state counters and applying any compensation for multiple package or multiple die systems.
--- drivers/thermal/intel/intel_powerclamp.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-)
drivers/thermal/intel/intel_powerclamp.c +16 -4
@@ -57,6 +57,7 @@static unsigned int target_mwait;static struct dentry *debug_dir; +static bool poll_pkg_cstate_enable;/* user selected target */ static unsigned int set_target_ratio;
@@ -262,6 +263,9 @@ static unsigned int get_compensation(int {unsigned int comp =0 ; +if (!poll_pkg_cstate_enable) +return 0 ; +/* we only use compensation if all adjacent ones are good */ if (ratio == 1 && cal_data[ratio].confidence >= CONFIDENCE_OK &&
@@ -534,7 +538,8 @@ static int start_power_clamp(void) control_cpu =cpumask_first (cpu_online_mask); clamping = true; -schedule_delayed_work (&poll_pkg_cstate_work,0 ); +if (poll_pkg_cstate_enable) +schedule_delayed_work (&poll_pkg_cstate_work,0 );/* start one kthread worker per online cpu */ for_each_online_cpu (cpu) {
@@ -603,11 +608,15 @@ static int powerclamp_get_max_state(strustatic int powerclamp_get_cur_state (struct thermal_cooling_device *cdev,unsigned long *state) { -if (true == clamping) - *state = pkg_cstate_ratio_cur; -else +if (clamping) { +if (poll_pkg_cstate_enable) + *state = pkg_cstate_ratio_cur; +else + *state = set_target_ratio; + }else {/* to save power, do not poll idle ratio while not clamping */ *state =-1 ;/* indicates invalid state */ + }return 0 ; }
@@ -732,6 +741,9 @@ static int __init powerclamp_init(void) goto exit_unregister; } +if (topology_max_packages () ==1 &&topology_max_die_per_package () ==1 ) + poll_pkg_cstate_enable = true; + cooling_dev =thermal_cooling_device_register ("intel_powerclamp" ,NULL , &powerclamp_cooling_ops);if (IS_ERR (cooling_dev)) {
Greg Kroah-Hartman
maintainerPATCH 389/529 dm flakey: fix logic when corrupting a bio
In reply to Greg Kroah-HartmanFrom: Mikulas Patocka <[email protected]>
commit aa56b9b75996ff4c76a0a4181c2fa0206c3d91cc upstream.
If "corrupt_bio_byte" is set to corrupt reads and corrupt_bio_flags is used, dm-flakey would erroneously return all writes as errors. Likewise, if "corrupt_bio_byte" is set to corrupt writes, dm-flakey would return errors for all reads.
Fix the logic so that if fc->corrupt_bio_byte is non-zero, dm-flakey will not abort reads on writes with an error.
--- drivers/md/dm-flakey.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-)
drivers/md/dm-flakey.c +13 -10
@@ -359,9 +359,11 @@ static int flakey_map(struct dm_target */* * Corrupt matching writes. */ -if (fc->corrupt_bio_byte && (fc->corrupt_bio_rw ==WRITE )) { -if (all_corrupt_bio_flags_match (bio, fc)) -corrupt_bio_data (bio, fc); +if (fc->corrupt_bio_byte) { +if (fc->corrupt_bio_rw ==WRITE ) { +if (all_corrupt_bio_flags_match (bio, fc)) +corrupt_bio_data (bio, fc); + } goto map_bio; }
@@ -387,13 +389,14 @@ static int flakey_end_io(struct dm_targereturn DM_ENDIO_DONE ;if (!*error && pb->bio_submitted && (bio_data_dir (bio) ==READ )) { -if (fc->corrupt_bio_byte && (fc->corrupt_bio_rw ==READ ) && -all_corrupt_bio_flags_match (bio, fc)) { -/* -* Corrupt successful matching READs while in down state. -*/ -corrupt_bio_data (bio, fc); - +if (fc->corrupt_bio_byte) { +if ((fc->corrupt_bio_rw ==READ ) && +all_corrupt_bio_flags_match (bio, fc)) { +/* +* Corrupt successful matching READs while in down state. +*/ +corrupt_bio_data (bio, fc); + } }else if (!test_bit (DROP_WRITES , &fc->flags) && !test_bit (ERROR_WRITES , &fc->flags)) {/*
Greg Kroah-Hartman
maintainerPATCH 390/529 dm flakey: dont corrupt the zero page
In reply to Greg Kroah-HartmanFrom: Mikulas Patocka <[email protected]>
commit f50714b57aecb6b3dc81d578e295f86d9c73f078 upstream.
When we need to zero some range on a block device, the function __blkdev_issue_zero_pages submits a write bio with the bio vector pointing to the zero page. If we use dm-flakey with corrupt bio writes option, it will corrupt the content of the zero page which results in crashes of various userspace programs. Glibc assumes that memory returned by mmap is zeroed and it uses it for calloc implementation; if the newly mapped memory is not zeroed, calloc will return non-zeroed memory.
Fix this bug by testing if the page is equal to ZERO_PAGE(0) and avoiding the corruption in this case.
--- drivers/md/dm-flakey.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/md/dm-flakey.c +5 -2
@@ -301,8 +301,11 @@ static void corrupt_bio_data(struct bio*/ bio_for_each_segment (bvec, bio, iter) {if (bio_iter_len (bio, iter) > corrupt_bio_byte) { -char *segment = (page_address (bio_iter_page (bio, iter)) - +bio_iter_offset (bio, iter)); +char *segment; +struct page *page =bio_iter_page (bio, iter); +if (unlikely (page ==ZERO_PAGE (0 ))) +break ; + segment = (page_address (page) +bio_iter_offset (bio, iter)); segment[corrupt_bio_byte] = fc->corrupt_bio_value; DMDEBUG("Corrupting data bio=%p by writing %u to byte %u " "(rw=%c bi_opf=%u bi_sector=%llu size=%u)\n",
Greg Kroah-Hartman
maintainerPATCH 391/529 ARM: dts: exynos: correct TMU phandle in Exynos4210
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
commit 408ab6786dbf6dd696488054c9559681112ef994 upstream.
TMU node uses 0 as thermal-sensor-cells, thus thermal zone referencing it must not have an argument to phandle. Since thermal-sensors property is already defined in included exynos4-cpu-thermal.dtsi, drop it from exynos4210.dtsi to fix the error and remoev redundancy.
--- arch/arm/boot/dts/exynos4210.dtsi | 1 - 1 file changed, 1 deletion(-)
arch/arm/boot/dts/exynos4210.dtsi +0 -1
@@ -382,7 +382,6 @@ &cpu_thermal { polling-delay-passive = <0>; polling-delay = <0>; - thermal-sensors = <&tmu 0>; }; &gic {
Greg Kroah-Hartman
maintainerPATCH 392/529 ARM: dts: exynos: correct TMU phandle in Exynos4
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
commit 8e4505e617a80f601e2f53a917611777f128f925 upstream.
TMU node uses 0 as thermal-sensor-cells, thus thermal zone referencing it must not have an argument to phandle.
--- arch/arm/boot/dts/exynos4-cpu-thermal.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/boot/dts/exynos4-cpu-thermal.dtsi +1 -1
@@ -10,7 +10,7 @@ / { thermal-zones { cpu_thermal: cpu-thermal { - thermal-sensors = <&tmu 0>; + thermal-sensors = <&tmu>; polling-delay-passive = <0>; polling-delay = <0>; trips {
Greg Kroah-Hartman
maintainerPATCH 393/529 ARM: dts: exynos: correct TMU phandle in Odroid XU3 family
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
commit a3583e92d188ec6c58c7f603ac5e72dd8a11c21a upstream.
TMU node uses 0 as thermal-sensor-cells, thus thermal zone referencing it must not have an argument to phandle. This was not critical before, but since rework of thermal Devicetree initialization in the commit 3fd6d6e2b4e8 ("thermal/of: Rework the thermal device tree initialization"), this leads to errors registering thermal zones other than first one:
thermal_sys: cpu0-thermal: Failed to read thermal-sensors cells: -2
thermal_sys: Failed to find thermal zone for tmu id=0 exynos-tmu 10064000.tmu: Failed to register sensor: -2
exynos-tmu: probe of 10064000.tmu failed with error -2
--- arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi +5 -5
@@ -50,7 +50,7 @@ thermal-zones { cpu0_thermal: cpu0-thermal { - thermal-sensors = <&tmu_cpu0 0>; + thermal-sensors = <&tmu_cpu0>; polling-delay-passive = <250>; polling-delay = <0>; trips {
@@ -139,7 +139,7 @@ }; }; cpu1_thermal: cpu1-thermal { - thermal-sensors = <&tmu_cpu1 0>; + thermal-sensors = <&tmu_cpu1>; polling-delay-passive = <250>; polling-delay = <0>; trips {
@@ -212,7 +212,7 @@ }; }; cpu2_thermal: cpu2-thermal { - thermal-sensors = <&tmu_cpu2 0>; + thermal-sensors = <&tmu_cpu2>; polling-delay-passive = <250>; polling-delay = <0>; trips {
@@ -285,7 +285,7 @@ }; }; cpu3_thermal: cpu3-thermal { - thermal-sensors = <&tmu_cpu3 0>; + thermal-sensors = <&tmu_cpu3>; polling-delay-passive = <250>; polling-delay = <0>; trips {
@@ -358,7 +358,7 @@ }; }; gpu_thermal: gpu-thermal { - thermal-sensors = <&tmu_gpu 0>; + thermal-sensors = <&tmu_gpu>; polling-delay-passive = <250>; polling-delay = <0>; trips {
Greg Kroah-Hartman
maintainerPATCH 394/529 ARM: dts: exynos: correct TMU phandle in Exynos5250
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
commit 33e2c595e2e4016991ead44933a29d1ef93d5f26 upstream.
TMU node uses 0 as thermal-sensor-cells, thus thermal zone referencing it must not have an argument to phandle.
--- arch/arm/boot/dts/exynos5250.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/boot/dts/exynos5250.dtsi +1 -1
@@ -1109,7 +1109,7 @@ &cpu_thermal { polling-delay-passive = <0>; polling-delay = <0>; - thermal-sensors = <&tmu 0>; + thermal-sensors = <&tmu>; cooling-maps { map0 {
Greg Kroah-Hartman
maintainerPATCH 395/529 ARM: dts: exynos: correct TMU phandle in Odroid XU
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
commit 9372eca505e7a19934d750b4b4c89a3652738e66 upstream.
TMU node uses 0 as thermal-sensor-cells, thus thermal zone referencing it must not have an argument to phandle. Since thermal-sensors property is already defined in included exynosi5410.dtsi, drop it from exynos5410-odroidxu.dts to fix the error and remoev redundancy.
--- arch/arm/boot/dts/exynos5410-odroidxu.dts | 1 - 1 file changed, 1 deletion(-)
arch/arm/boot/dts/exynos5410-odroidxu.dts +0 -1
@@ -116,7 +116,6 @@ }; &cpu0_thermal { - thermal-sensors = <&tmu_cpu0 0>; polling-delay-passive = <0>; polling-delay = <0>;
Greg Kroah-Hartman
maintainerPATCH 396/529 ARM: dts: exynos: correct TMU phandle in Odroid HC1
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
commit 2e3d0e20d8456f876607a8af61fdb83dfbf98cb6 upstream.
TMU node uses 0 as thermal-sensor-cells, thus thermal zone referencing it must not have an argument to phandle. This was not critical before, but since rework of thermal Devicetree initialization in the commit 3fd6d6e2b4e8 ("thermal/of: Rework the thermal device tree initialization"), this leads to errors registering thermal zones other than first one:
thermal_sys: cpu0-thermal: Failed to read thermal-sensors cells: -2
thermal_sys: Failed to find thermal zone for tmu id=0 exynos-tmu 10064000.tmu: Failed to register sensor: -2
exynos-tmu: probe of 10064000.tmu failed with error -2
--- arch/arm/boot/dts/exynos5422-odroidhc1.dts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
arch/arm/boot/dts/exynos5422-odroidhc1.dts +5 -5
@@ -29,7 +29,7 @@ thermal-zones { cpu0_thermal: cpu0-thermal { - thermal-sensors = <&tmu_cpu0 0>; + thermal-sensors = <&tmu_cpu0>; trips { cpu0_alert0: cpu-alert-0 { temperature = <70000>; /* millicelsius */
@@ -84,7 +84,7 @@ }; }; cpu1_thermal: cpu1-thermal { - thermal-sensors = <&tmu_cpu1 0>; + thermal-sensors = <&tmu_cpu1>; trips { cpu1_alert0: cpu-alert-0 { temperature = <70000>;
@@ -128,7 +128,7 @@ }; }; cpu2_thermal: cpu2-thermal { - thermal-sensors = <&tmu_cpu2 0>; + thermal-sensors = <&tmu_cpu2>; trips { cpu2_alert0: cpu-alert-0 { temperature = <70000>;
@@ -172,7 +172,7 @@ }; }; cpu3_thermal: cpu3-thermal { - thermal-sensors = <&tmu_cpu3 0>; + thermal-sensors = <&tmu_cpu3>; trips { cpu3_alert0: cpu-alert-0 { temperature = <70000>;
@@ -216,7 +216,7 @@ }; }; gpu_thermal: gpu-thermal { - thermal-sensors = <&tmu_gpu 0>; + thermal-sensors = <&tmu_gpu>; trips { gpu_alert0: gpu-alert-0 { temperature = <70000>;
Greg Kroah-Hartman
maintainerPATCH 397/529 rbd: avoid use-after-free in do_rbd_add() when rbd_dev_create() fails
In reply to Greg Kroah-HartmanFrom: Ilya Dryomov <[email protected]>
commit f7c4d9b133c7a04ca619355574e96b6abf209fba upstream.
If getting an ID or setting up a work queue in rbd_dev_create() fails, use-after-free on rbd_dev->rbd_client, rbd_dev->spec and rbd_dev->opts is triggered in do_rbd_add(). The root cause is that the ownership of these structures is transfered to rbd_dev prematurely and they all end up getting freed when rbd_dev_create() calls rbd_dev_free() prior to returning to do_rbd_add().
Found by Linux Verification Center (linuxtesting.org) with SVACE, an incomplete patch submitted by Natalia Petrova <[email protected]>.
--- drivers/block/rbd.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-)
drivers/block/rbd.c +9 -11
@@ -5369,8 +5369,7 @@ static void rbd_dev_release(struct devicmodule_put (THIS_MODULE ); } -static struct rbd_device *__rbd_dev_create (struct rbd_client *rbdc, -struct rbd_spec *spec) +static struct rbd_device *__rbd_dev_create (struct rbd_spec *spec) {struct rbd_device *rbd_dev;
@@ -5415,9 +5414,6 @@ static struct rbd_device *__rbd_dev_crea rbd_dev->dev.parent = &rbd_root_dev;device_initialize (&rbd_dev->dev); - rbd_dev->rbd_client = rbdc; - rbd_dev->spec = spec; -return rbd_dev; }
@@ -5430,12 +5426,10 @@ static struct rbd_device *rbd_dev_create {struct rbd_device *rbd_dev; - rbd_dev =__rbd_dev_create (rbdc, spec); + rbd_dev =__rbd_dev_create (spec);if (!rbd_dev)return NULL ; - rbd_dev->opts = opts; -/* get an id and fill in device name */ rbd_dev->dev_id = ida_simple_get(&rbd_dev_id_ida, 0, minor_to_rbd_dev_id(1 << MINORBITS),
@@ -5452,6 +5446,10 @@ static struct rbd_device *rbd_dev_create/* we have a ref from do_rbd_add() */ __module_get (THIS_MODULE ); + rbd_dev->rbd_client = rbdc; + rbd_dev->spec = spec; + rbd_dev->opts = opts; +dout ("%s rbd_dev %p dev_id %d\n" , __func__, rbd_dev, rbd_dev->dev_id);return rbd_dev;
@@ -6812,7 +6810,7 @@ static int rbd_dev_probe_parent(struct r goto out_err; } - parent =__rbd_dev_create (rbd_dev->rbd_client, rbd_dev->parent_spec); + parent =__rbd_dev_create (rbd_dev->parent_spec);if (!parent) { ret = -ENOMEM ; goto out_err;
@@ -6822,8 +6820,8 @@ static int rbd_dev_probe_parent(struct r* Images related by parent/child relationships always share * rbd_client and spec/parent_spec, so bump their refcounts. */ -__rbd_get_client (rbd_dev->rbd_client); -rbd_spec_get (rbd_dev->parent_spec); + parent->rbd_client =__rbd_get_client (rbd_dev->rbd_client); + parent->spec =rbd_spec_get (rbd_dev->parent_spec);__set_bit (RBD_DEV_FLAG_READONLY , &parent->flags);
Greg Kroah-Hartman
maintainerPATCH 398/529 alpha: fix FEN fault handling
In reply to Greg Kroah-HartmanFrom: Al Viro <[email protected]>
commit 977a3009547dad4a5bc95d91be4a58c9f7eedac0 upstream.
Type 3 instruction fault (FPU insn with FPU disabled) is handled by quietly enabling FPU and returning. Which is fine, except that we need to do that both for fault in userland and in the kernel; the latter *can* legitimately happen - all it takes is this:
.global _start_start:
call_pal 0xae lda $0, 0 ldq $0, 0($0)
- call_pal CLRFEN to clear "FPU enabled" flag and arrange for a signal delivery (SIGSEGV in this case).
Fixed by moving the handling of type 3 into the common part of do_entIF(), before we check for kernel vs. user mode.
Incidentally, the check for kernel mode is unidiomatic; the normal way to do that is !user_mode(regs). The difference is that the open-coded variant treats any of bits 63..3 of regs->ps being set as "it's user mode" while the normal approach is to check just the bit 3. PS is a 4-bit register and regs->ps always will have bits 63..4 clear, so the open-coded variant here is actually equivalent to !user_mode(regs). Harder to follow, though...
--- arch/alpha/kernel/traps.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-)
arch/alpha/kernel/traps.c +15 -15
@@ -235,7 +235,21 @@ do_entIF(unsigned long type, struct pt_r {int signo, code; -if ((regs->ps & ~IPL_MAX ) ==0 ) { +if (type ==3 ) {/* FEN fault */ +/* Irritating users can call PAL_clrfen to disable the +FPU for the process. The kernel will then trap in +do_switch_stack and undo_switch_stack when we try +to save and restore the FP registers. + +Given that GCC by default generates code that uses the +FP registers, PAL_clrfen is not useful except for DoS +attacks. So turn the bleeding FPU back on and be done +with it. */ +current_thread_info ()->pcb.flags |=1 ; +__reload_thread (¤t_thread_info ()->pcb); +return ; + } +if (!user_mode (regs)) {if (type ==1 ) {const unsigned int *data = (const unsigned int *) regs->pc;
@@ -368,20 +382,6 @@ do_entIF(unsigned long type, struct pt_r }break ; -case 3 :/* FEN fault */ -/* Irritating users can call PAL_clrfen to disable the -FPU for the process. The kernel will then trap in -do_switch_stack and undo_switch_stack when we try -to save and restore the FP registers. - -Given that GCC by default generates code that uses the -FP registers, PAL_clrfen is not useful except for DoS -attacks. So turn the bleeding FPU back on and be done -with it. */ -current_thread_info ()->pcb.flags |=1 ; -__reload_thread (¤t_thread_info ()->pcb); -return ; -case 5 :/* illoc */ default :/* unexpected instruction-fault type */ ;
Greg Kroah-Hartman
maintainerPATCH 399/529 dax/kmem: Fix leak of memory-hotplug resources
In reply to Greg Kroah-HartmanFrom: Dan Williams <[email protected]>
commit e686c32590f40bffc45f105c04c836ffad3e531a upstream.
While experimenting with CXL region removal the following corruption of /proc/iomem appeared.
Before:
f010000000-f04fffffff : CXL Window 0
f010000000-f02fffffff : region4
f010000000-f02fffffff : dax4.0
f010000000-f02fffffff : System RAM (kmem)After (modprobe -r cxl_test):
f010000000-f02fffffff : **redacted binary garbage**
f010000000-f02fffffff : System RAM (kmem)
...and testing further the same is visible with persistent memory assigned to kmem:
Before:
480000000-243fffffff : Persistent Memory
480000000-57e1fffff : namespace3.0
580000000-243fffffff : dax3.0
580000000-243fffffff : System RAM (kmem)
After (ndctl disable-region all):
480000000-243fffffff : Persistent Memory
580000000-243fffffff : ***redacted binary garbage***
580000000-243fffffff : System RAM (kmem)
The corrupted data is from a use-after-free of the "dax4.0" and "dax3.0" resources, and it also shows that the "System RAM (kmem)" resource is not being removed. The bug does not appear after "modprobe -r kmem", it requires the parent of "dax4.0" and "dax3.0" to be removed which re-parents the leaked "System RAM (kmem)" instances. Those in turn reference the freed resource as a parent.
First up for the fix is release_mem_region_adjustable() needs to reliably delete the resource inserted by add_memory_driver_managed(). That is thwarted by a check for IORESOURCE_SYSRAM that predates the dax/kmem driver, from commit:
65c78784135f ("kernel, resource: check for IORESOURCE_SYSRAM in release_mem_region_adjustable")
That appears to be working around the behavior of HMM's "MEMORY_DEVICE_PUBLIC" facility that has since been deleted. With that check removed the "System RAM (kmem)" resource gets removed, but corruption still occurs occasionally because the "dax" resource is not reliably removed.
The dax range information is freed before the device is unregistered, so the driver can not reliably recall (another use after free) what it is meant to release. Lastly if that use after free got lucky, the driver was covering up the leak of "System RAM (kmem)" due to its use of release_resource() which detaches, but does not free, child resources. The switch to remove_resource() forces remove_memory() to be responsible for the deletion of the resource added by add_memory_driver_managed().
--- drivers/dax/bus.c | 2 +- drivers/dax/kmem.c | 4 ++-- kernel/resource.c | 14 -------------- 3 files changed, 3 insertions(+), 17 deletions(-)
drivers/dax/bus.c +1 -1
@@ -398,8 +398,8 @@ static void unregister_dev_dax(void *devdev_dbg (dev,"%s\n" , __func__);kill_dev_dax (dev_dax); -free_dev_dax_ranges (dev_dax);device_del (dev); +free_dev_dax_ranges (dev_dax);put_device (dev); }
drivers/dax/kmem.c +2 -2
@@ -114,7 +114,7 @@ static int dev_dax_kmem_probe(struct devif (rc) {dev_warn (dev,"mapping%d: %#llx-%#llx memory add failed\n" , i, range.start, range.end); -release_resource (res); +remove_resource (res);kfree (res); data->res[i] =NULL ;if (mapped)
@@ -159,7 +159,7 @@ static int dev_dax_kmem_remove(struct de rc =remove_memory (dev_dax->target_node, range.start,range_len (&range));if (rc ==0 ) { -release_resource (data->res[i]); +remove_resource (data->res[i]);kfree (data->res[i]); data->res[i] =NULL ; success++;
kernel/resource.c +0 -14
@@ -1293,20 +1293,6 @@ retry:continue ; } -/* -* All memory regions added from memory-hotplug path have the -* flag IORESOURCE_SYSTEM_RAM. If the resource does not have -* this flag, we know that we are dealing with a resource coming -* from HMM/devm. HMM/devm use another mechanism to add/release -* a resource. This goes via devm_request_mem_region and -* devm_release_mem_region. -* HMM/devm take care to release their resources when they want, -* so if we are dealing with them, let us just back off here. -*/ -if (!(res->flags &IORESOURCE_SYSRAM )) { -break ; - } -if (!(res->flags &IORESOURCE_MEM ))break ;
Greg Kroah-Hartman
maintainerPATCH 400/529 mips: fix syscall_get_nr
In reply to Greg Kroah-HartmanFrom: Elvira Khabirova <[email protected]>
commit 85cc91e2ba4262a602ec65e2b76c4391a9e60d3d upstream.
The implementation of syscall_get_nr on mips used to ignore the task argument and return the syscall number of the calling thread instead of the target thread.
The bug was exposed to user space by commit 201766a20e30f ("ptrace: add PTRACE_GET_SYSCALL_INFO request") and detected by strace test suite.
--- arch/mips/include/asm/syscall.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/mips/include/asm/syscall.h +1 -1
@@ -38,7 +38,7 @@ static inline bool mips_syscall_is_indirstatic inline long syscall_get_nr (struct task_struct *task,struct pt_regs *regs) { -return current_thread_info ()->syscall; +return task_thread_info (task)->syscall; } static inline void mips_syscall_update_nr(struct task_struct *task,
Greg Kroah-Hartman
maintainerPATCH 401/529 media: ipu3-cio2: Fix PM runtime usage_count in driver unbind
In reply to Greg Kroah-HartmanFrom: Sakari Ailus <[email protected]>
commit 909d3096ac99fa2289f9b8945a3eab2269947a0a upstream.
Get the PM runtime usage_count and forbid PM runtime at driver unbind. The opposite is being done in probe() already.
--- drivers/media/pci/intel/ipu3/ipu3-cio2.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/media/pci/intel/ipu3/ipu3-cio2.c +3 -0
@@ -1831,6 +1831,9 @@ static void cio2_pci_remove(struct pci_dv4l2_device_unregister (&cio2->v4l2_dev);media_device_cleanup (&cio2->media_dev);mutex_destroy (&cio2->lock); + +pm_runtime_forbid (&pci_dev->dev); +pm_runtime_get_noresume (&pci_dev->dev); }static int __maybe_unused cio2_runtime_suspend (struct device *dev)
Greg Kroah-Hartman
maintainerPATCH 402/529 remoteproc/mtk_scp: Move clk ops outside send_lock
In reply to Greg Kroah-HartmanFrom: Chen-Yu Tsai <[email protected]>
commit e46ceea3148163166ef9b7bcac578e72dd30c064 upstream.
Clocks are properly reference counted and do not need to be inside the lock range.
Right now this triggers a false-positive lockdep warning on MT8192 based Chromebooks, through a combination of mtk-scp that has a cros-ec-rpmsg sub-device, the (actual) cros-ec I2C adapter registration, I2C client (not on cros-ec) probe doing i2c transfers and enabling clocks.
This is a false positive because the cros-ec-rpmsg under mtk-scp does not have an I2C adapter, and also each I2C adapter and cros-ec instance have their own mutex.
Move the clk operations outside of the send_lock range.
--- drivers/remoteproc/mtk_scp_ipi.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
drivers/remoteproc/mtk_scp_ipi.c +5 -6
@@ -164,21 +164,21 @@ int scp_ipi_send(struct mtk_scp *scp, u3 WARN_ON(len > sizeof(send_obj->share_buf)) || WARN_ON(!buf))return -EINVAL ; -mutex_lock (&scp->send_lock); - ret =clk_prepare_enable (scp->clk);if (ret) {dev_err (scp->dev,"failed to enable clock\n" ); - goto unlock_mutex; +return ret; } +mutex_lock (&scp->send_lock); +/* Wait until SCP receives the last command */ timeout = jiffies +msecs_to_jiffies (2000 );do {if (time_after (jiffies, timeout)) {dev_err (scp->dev,"%s: IPI timeout!\n" , __func__); ret = -ETIMEDOUT ; - goto clock_disable; + goto unlock_mutex; } }while (readl (scp->reg_base + scp->data->host_to_scp_reg));
@@ -205,10 +205,9 @@ int scp_ipi_send(struct mtk_scp *scp, u3 ret =0 ; } -clock_disable: -clk_disable_unprepare (scp->clk); unlock_mutex:mutex_unlock (&scp->send_lock); +clk_disable_unprepare (scp->clk);return ret; }
Greg Kroah-Hartman
maintainerPATCH 403/529 docs: gdbmacros: print newest record
In reply to Greg Kroah-HartmanFrom: John Ogness <[email protected]>
commit f2e4cca2f670c8e52fbb551a295f2afc9aa2bd72 upstream.
@head_id points to the newest record, but the printing loop exits when it increments to this value (before printing).
Exit the printing loop after the newest record has been printed.
The python-based function in scripts/gdb/linux/dmesg.py already does this correctly.
--- Documentation/admin-guide/kdump/gdbmacros.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Documentation/admin-guide/kdump/gdbmacros.txt +1 -1
@@ -312,10 +312,10 @@ define dmesg set var $prev_flags = $info->flags end - set var $id = ($id + 1) & $id_mask if ($id == $end_id) loop_break end + set var $id = ($id + 1) & $id_mask end end document dmesg
Greg Kroah-Hartman
maintainerPATCH 404/529 mm: memcontrol: deprecate charge moving
In reply to Greg Kroah-HartmanFrom: Johannes Weiner <[email protected]>
commit da34a8484d162585e22ed8c1e4114aa2f60e3567 upstream.
Charge moving mode in cgroup1 allows memory to follow tasks as they migrate between cgroups. This is, and always has been, a questionable thing to do - for several reasons.
First, it's expensive. Pages need to be identified, locked and isolated from various MM operations, and reassigned, one by one.
Second, it's unreliable. Once pages are charged to a cgroup, there isn't always a clear owner task anymore. Cache isn't moved at all, for example. Mapped memory is moved - but if trylocking or isolating a page fails, it's arbitrarily left behind. Frequent moving between domains may leave a task's memory scattered all over the place.
Third, it isn't really needed. Launcher tasks can kick off workload tasks directly in their target cgroup. Using dedicated per-workload groups allows fine-grained policy adjustments - no need to move tasks and their physical pages between control domains. The feature was never forward-ported to cgroup2, and it hasn't been missed.
Despite it being a niche usecase, the maintenance overhead of supporting it is enormous. Because pages are moved while they are live and subject to various MM operations, the synchronization rules are complicated. There are lock_page_memcg() in MM and FS code, which non-cgroup people don't understand. In some cases we've been able to shift code and cgroup API calls around such that we can rely on native locking as much as possible. But that's fragile, and sometimes we need to hold MM locks for longer than we otherwise would (pte lock e.g.).
Mark the feature deprecated. Hopefully we can remove it soon.
And backport into -stable kernels so that people who develop against earlier kernels are warned about this deprecation as early as possible.
--- Documentation/admin-guide/cgroup-v1/memory.rst | 13 +++++++++++-- mm/memcontrol.c | 4 ++++ 2 files changed, 15 insertions(+), 2 deletions(-)
Documentation/admin-guide/cgroup-v1/memory.rst +11 -2
@@ -82,6 +82,8 @@ Brief summary of control files. memory.swappiness set/show swappiness parameter of vmscan (See sysctl's vm.swappiness) memory.move_charge_at_immigrate set/show controls of moving charges + This knob is deprecated and shouldn't be + used. memory.oom_control set/show oom controls. memory.numa_stat show the number of memory usage per numa node
@@ -740,8 +742,15 @@ NOTE2: It is recommended to set the soft limit always below the hard limit, otherwise the hard limit will take precedence. -8. Move charges at task migration -================================= +8. Move charges at task migration (DEPRECATED!) +=============================================== + +THIS IS DEPRECATED! + +It's expensive and unreliable! It's better practice to launch workload +tasks directly from inside their target cgroup. Use dedicated workload +cgroups to allow fine-grained policy adjustments without having to +move physical pages between control domains. Users can move charges associated with a task along with task migration, that is, uncharge task's pages from the old cgroup and charge them to the new cgroup.
mm/memcontrol.c +4 -0
@@ -3930,6 +3930,10 @@ static int mem_cgroup_move_charge_write( {struct mem_cgroup *memcg =mem_cgroup_from_css (css); +pr_warn_once ("Cgroup memory moving (move_charge_at_immigrate) is deprecated. " +"Please report your usecase to [email protected] if you " +"depend on this functionality.\n" ); +if (val & ~MOVE_MASK )return -EINVAL ;
Greg Kroah-Hartman
maintainerPATCH 405/529 mm/thp: check and bail out if page in deferred queue already
In reply to Greg Kroah-HartmanFrom: Yin Fengwei <[email protected]>
commit 81e506bec9be1eceaf5a2c654e28ba5176ef48d8 upstream.
Kernel build regression with LLVM was reported here:
https://lore.kernel.org/all/Y1GCYXGtEVZbcv%[email protected]/ with commit f35b5d7d676e ("mm: align larger anonymous mappings on THP boundaries"). And the commit f35b5d7d676e was reverted.
It turned out the regression is related with madvise(MADV_DONTNEED) was used by ld.lld. But with none PMD_SIZE aligned parameter len. trace-bpfcc captured:
531607 531732 ld.lld do_madvise.part.0 start: 0x7feca9000000, len: 0x7fb000, behavior: 0x4 531607 531793 ld.lld do_madvise.part.0 start: 0x7fec86a00000, len: 0x7fb000, behavior: 0x4
If the underneath physical page is THP, the madvise(MADV_DONTNEED) can trigger split_queue_lock contention raised significantly. perf showed following data:
14.85% 0.00% ld.lld [kernel.kallsyms] [k]
entry_SYSCALL_64_after_hwframe
11.52%
entry_SYSCALL_64_after_hwframe
do_syscall_64
__x64_sys_madvise
do_madvise.part.0
zap_page_range
unmap_single_vma
unmap_page_range
page_remove_rmap
deferred_split_huge_page
__lock_text_start
native_queued_spin_lock_slowpathIf THP can't be removed from rmap as whole THP, partial THP will be removed from rmap by removing sub-pages from rmap. Even the THP head page is added to deferred queue already, the split_queue_lock will be acquired and check whether the THP head page is in the queue already. Thus, the contention of split_queue_lock is raised.
Before acquire split_queue_lock, check and bail out early if the THP head page is in the queue already. The checking without holding split_queue_lock could race with deferred_split_scan, but it doesn't impact the correctness here.
Test result of building kernel with ld.lld:
commit 7b5a0b664ebe (parent commit of f35b5d7d676e):
time -f "\t%E real,\t%U user,\t%S sys" make LD=ld.lld -skj96 allmodconfig all
6:07.99 real, 26367.77 user, 5063.35 sys
commit f35b5d7d676e:
time -f "\t%E real,\t%U user,\t%S sys" make LD=ld.lld -skj96 allmodconfig all
7:22.15 real, 26235.03 user, 12504.55 sys
commit f35b5d7d676e with the fixing patch:
time -f "\t%E real,\t%U user,\t%S sys" make LD=ld.lld -skj96 allmodconfig all
6:08.49 real, 26520.15 user, 5047.91 sys
--- mm/huge_memory.c | 3 +++ 1 file changed, 3 insertions(+)
mm/huge_memory.c +3 -0
@@ -2803,6 +2803,9 @@ void deferred_split_huge_page(struct pagif (PageSwapCache (page))return ; +if (!list_empty (page_deferred_list (page))) +return ; +spin_lock_irqsave (&ds_queue->split_queue_lock, flags);if (list_empty (page_deferred_list (page))) {count_vm_event (THP_DEFERRED_SPLIT_PAGE );
Greg Kroah-Hartman
maintainerPATCH 406/529 ktest.pl: Give back console on Ctrt^C on monitor
In reply to Greg Kroah-HartmanFrom: Steven Rostedt <[email protected]>
commit 83d29d439cd3ef23041570d55841f814af2ecac0 upstream.
When monitoring the console output, the stdout is being redirected to do so. If Ctrl^C is hit during this mode, the stdout is not back to the console, the user does not see anything they type (no echo).
Add "end_monitor" to the SIGINT interrupt handler to give back the console on Ctrl^C.
--- tools/testing/ktest/ktest.pl | 3 +++ 1 file changed, 3 insertions(+)
tools/testing/ktest/ktest.pl +3 -0
@@ -4283,6 +4283,9 @@ sub send_email { } sub cancel_test { + if ($monitor_cnt) { + end_monitor; + } if ($email_when_canceled) { my $name = get_test_name; send_email("KTEST: Your [$name] test was cancelled",
Greg Kroah-Hartman
maintainerPATCH 407/529 ktest.pl: Fix missing "end_monitor" when machine check fails
In reply to Greg Kroah-HartmanFrom: Steven Rostedt <[email protected]>
commit e8bf9b98d40dbdf4e39362e3b85a70c61da68cb7 upstream.
In the "reboot" command, it does a check of the machine to see if it is still alive with a simple "ssh echo" command. If it fails, it will assume that a normal "ssh reboot" is not possible and force a power cycle.
In this case, the "start_monitor" is executed, but the "end_monitor" is not, and this causes the screen will not be given back to the console. That is, after the test, a "reset" command needs to be performed, as "echo" is turned off.
--- tools/testing/ktest/ktest.pl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/testing/ktest/ktest.pl +2 -1
@@ -1433,7 +1433,8 @@ sub reboot { # Still need to wait for the reboot to finish wait_for_monitor($time, $reboot_success_line); - + } + if ($powercycle || $time) { end_monitor; } }
Greg Kroah-Hartman
maintainerPATCH 408/529 ktest.pl: Add RUN_TIMEOUT option with default unlimited
In reply to Greg Kroah-HartmanFrom: Steven Rostedt <[email protected]>
commit 4e7d2a8f0b52abf23b1dc13b3d88bc0923383cd5 upstream.
There is a disconnect between the run_command function and the wait_for_input. The wait_for_input has a default timeout of 2 minutes. But if that happens, the run_command loop will exit out to the waitpid() of the executing command. This fails in that it no longer monitors the command, and also, the ssh to the test box can hang when its finished, as it's waiting for the pipe it's writing to to flush, but the loop that reads that pipe has already exited, leaving the command stuck, and the test hangs.
Instead, make the default "wait_for_input" of the run_command infinite, and allow the user to override it if they want with a default timeout option "RUN_TIMEOUT".
But this fixes the hang that happens when the pipe is full and the ssh session never exits.
--- tools/testing/ktest/ktest.pl | 20 ++++++++++++++++---- tools/testing/ktest/sample.conf | 5 +++++ 2 files changed, 21 insertions(+), 4 deletions(-)
tools/testing/ktest/ktest.pl +16 -4
@@ -178,6 +178,7 @@ my $store_failures; my $store_successes; my $test_name; my $timeout; +my $run_timeout; my $connect_timeout; my $config_bisect_exec; my $booted_timeout;
@@ -340,6 +341,7 @@ my %option_map = ( "STORE_SUCCESSES" => \$store_successes, "TEST_NAME" => \$test_name, "TIMEOUT" => \$timeout, + "RUN_TIMEOUT" => \$run_timeout, "CONNECT_TIMEOUT" => \$connect_timeout, "CONFIG_BISECT_EXEC" => \$config_bisect_exec, "BOOTED_TIMEOUT" => \$booted_timeout,
@@ -1800,6 +1802,14 @@ sub run_command { $command =~ s/\$SSH_USER/$ssh_user/g; $command =~ s/\$MACHINE/$machine/g; + if (!defined($timeout)) { + $timeout = $run_timeout; + } + + if (!defined($timeout)) { + $timeout = -1; # tell wait_for_input to wait indefinitely + } + doprint("$command ... "); $start_time = time;
@@ -1826,13 +1836,10 @@ sub run_command { while (1) { my $fp = \*CMD; - if (defined($timeout)) { - doprint "timeout = $timeout\n"; - } my $line = wait_for_input($fp, $timeout); if (!defined($line)) { my $now = time; - if (defined($timeout) && (($now - $start_time) >= $timeout)) { + if ($timeout >= 0 && (($now - $start_time) >= $timeout)) { doprint "Hit timeout of $timeout, killing process\n"; $hit_timeout = 1; kill 9, $pid;
@@ -2005,6 +2012,11 @@ sub wait_for_input $time = $timeout; } + if ($time < 0) { + # Negative number means wait indefinitely + undef $time; + } + $rin = ''; vec($rin, fileno($fp), 1) = 1; vec($rin, fileno(\*STDIN), 1) = 1;
tools/testing/ktest/sample.conf +5 -0
@@ -809,6 +809,11 @@ # is issued instead of a reboot. # CONNECT_TIMEOUT = 25 +# The timeout in seconds for how long to wait for any running command +# to timeout. If not defined, it will let it go indefinitely. +# (default undefined) +#RUN_TIMEOUT = 600 + # In between tests, a reboot of the box may occur, and this # is the time to wait for the console after it stops producing # output. Some machines may not produce a large lag on reboot
Greg Kroah-Hartman
maintainerPATCH 409/529 ring-buffer: Handle race between rb_move_tail and rb_check_pages
In reply to Greg Kroah-HartmanFrom: Mukesh Ojha <[email protected]>
commit 8843e06f67b14f71c044bf6267b2387784c7e198 upstream.
It seems a data race between ring_buffer writing and integrity check. That is, RB_FLAG of head_page is been updating, while at same time RB_FLAG was cleared when doing integrity check rb_check_pages():
rb_check_pages() rb_handle_head_page():
-------- --------
rb_head_page_deactivate()
rb_head_page_set_normal()
rb_head_page_activate()
We do intergrity test of the list to check if the list is corrupted and it is still worth doing it. So, let's refactor rb_check_pages() such that we no longer clear and set flag during the list sanity checking.
[1] and [2] are the test to reproduce and the crash report respectively.
1:
``` read_trace.sh
while true;
do
# the "trace" file is closed after read
head -1 /sys/kernel/tracing/trace > /dev/null
done
```
``` repro.sh
sysctl -w kernel.panic_on_warn=1
# function tracer will writing enough data into ring_buffer
echo function > /sys/kernel/tracing/current_tracer
./read_trace.sh &
./read_trace.sh &
./read_trace.sh &
./read_trace.sh &
./read_trace.sh &
./read_trace.sh &
./read_trace.sh &
./read_trace.sh &
```2:
------------[ cut here ]------------ WARNING: CPU: 9 PID: 62 at kernel/trace/ring_buffer.c:2653 rb_move_tail+0x450/0x470 Modules linked in: CPU: 9 PID: 62 Comm: ksoftirqd/9 Tainted: G W 6.2.0-rc6+ Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.15.0-0-g2dd4b9b3f840-prebuilt.qemu.org 04/01/2014 RIP: 0010:rb_move_tail+0x450/0x470 Code: ff ff 4c 89 c8 f0 4d 0f b1 02 48 89 c2 48 83 e2 fc 49 39 d0 75 24 83 e0 03 83 f8 02 0f 84 e1 fb ff ff 48 8b 57 10 f0 ff 42 08 <0f> 0b 83 f8 02 0f 84 ce fb ff ff e9 db RSP: 0018:ffffb5564089bd00 EFLAGS: 00000203 RAX: 0000000000000000 RBX: ffff9db385a2bf81 RCX: ffffb5564089bd18 RDX: ffff9db281110100 RSI: 0000000000000fe4 RDI: ffff9db380145400 RBP: ffff9db385a2bf80 R08: ffff9db385a2bfc0 R09: ffff9db385a2bfc2 R10: ffff9db385a6c000 R11: ffff9db385a2bf80 R12: 0000000000000000 R13: 00000000000003e8 R14: ffff9db281110100 R15: ffffffffbb006108 FS: 0000000000000000(0000) GS:ffff9db3bdcc0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00005602323024c8 CR3: 0000000022e0c000 CR4: 00000000000006e0 Call Trace: <TASK> ring_buffer_lock_reserve+0x136/0x360 ? __do_softirq+0x287/0x2df ? __pfx_rcu_softirq_qs+0x10/0x10 trace_function+0x21/0x110 ? __pfx_rcu_softirq_qs+0x10/0x10 ? __do_softirq+0x287/0x2df function_trace_call+0xf6/0x120 0xffffffffc038f097 ? rcu_softirq_qs+0x5/0x140 rcu_softirq_qs+0x5/0x140 __do_softirq+0x287/0x2df run_ksoftirqd+0x2a/0x30 smpboot_thread_fn+0x188/0x220 ? __pfx_smpboot_thread_fn+0x10/0x10 kthread+0xe7/0x110 ? __pfx_kthread+0x10/0x10 ret_from_fork+0x2c/0x50 </TASK> ---[ end trace 0000000000000000 ]---
[ crash report and test reproducer credit goes to Zheng Yejian]
--- kernel/trace/ring_buffer.c | 42 ++++++++++-------------------------------- 1 file changed, 10 insertions(+), 32 deletions(-)
kernel/trace/ring_buffer.c +10 -32
@@ -1450,19 +1450,6 @@ static int rb_check_bpage(struct ring_bu }/** -* rb_check_list - make sure a pointer to a list has the last bits zero -*/ -static int rb_check_list (struct ring_buffer_per_cpu *cpu_buffer, -struct list_head *list) -{ -if (RB_WARN_ON (cpu_buffer,rb_list_head (list->prev) != list->prev)) -return 1 ; -if (RB_WARN_ON (cpu_buffer,rb_list_head (list->next) != list->next)) -return 1 ; -return 0 ; -} - -/** * rb_check_pages - integrity check of buffer pages * @cpu_buffer: CPU buffer with pages to test *
@@ -1471,36 +1458,27 @@ static int rb_check_list(struct ring_buf*/ static int rb_check_pages (struct ring_buffer_per_cpu *cpu_buffer) { -struct list_head *head = cpu_buffer->pages; -struct buffer_page *bpage, *tmp; +struct list_head *head =rb_list_head (cpu_buffer->pages); +struct list_head *tmp; -/* Reset the head page if it exists */ -if (cpu_buffer->head_page) -rb_set_head_page (cpu_buffer); - -rb_head_page_deactivate (cpu_buffer); - -if (RB_WARN_ON (cpu_buffer, head->next->prev != head)) -return -1 ; -if (RB_WARN_ON (cpu_buffer, head->prev->next != head)) +if (RB_WARN_ON (cpu_buffer, +rb_list_head (rb_list_head (head->next)->prev) != head))return -1 ; -if (rb_check_list (cpu_buffer, head)) +if (RB_WARN_ON (cpu_buffer, +rb_list_head (rb_list_head (head->prev)->next) != head))return -1 ; -list_for_each_entry_safe (bpage, tmp, head, list) { +for (tmp =rb_list_head (head->next); tmp != head; tmp =rb_list_head (tmp->next)) {if (RB_WARN_ON (cpu_buffer, - bpage->list.next->prev != &bpage->list)) +rb_list_head (rb_list_head (tmp->next)->prev) != tmp))return -1 ; +if (RB_WARN_ON (cpu_buffer, - bpage->list.prev->next != &bpage->list)) -return -1 ; -if (rb_check_list (cpu_buffer, &bpage->list)) +rb_list_head (rb_list_head (tmp->prev)->next) != tmp))return -1 ; } -rb_head_page_activate (cpu_buffer); -return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 410/529 scsi: qla2xxx: Fix link failure in NPIV environment
In reply to Greg Kroah-HartmanFrom: Quinn Tran <[email protected]>
commit b1ae65c082f74536ec292b15766f2846f0238373 upstream.
User experienced symptoms of adapter failure in NPIV environment. NPIV hosts were allowed to trigger chip reset back to back due to NPIV link state being slow to come online.
Fix link failure in NPIV environment by removing NPIV host from directly being able to perform chip reset.
kernel: qla2xxx [0000:04:00.1]-6009:261: Loop down - aborting ISP.
kernel: qla2xxx [0000:04:00.1]-6009:262: Loop down - aborting ISP.
kernel: qla2xxx [0000:04:00.1]-6009:281: Loop down - aborting ISP.
kernel: qla2xxx [0000:04:00.1]-6009:285: Loop down - aborting ISP
--- drivers/scsi/qla2xxx/qla_os.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/qla2xxx/qla_os.c +1 -1
@@ -7145,7 +7145,7 @@ qla2x00_timer(struct timer_list *t)/* if the loop has been down for 4 minutes, reinit adapter */ if (atomic_dec_and_test (&vha->loop_down_timer) !=0 ) { -if (!(vha->device_flags &DFLG_NO_CABLE )) { +if (!(vha->device_flags &DFLG_NO_CABLE ) && !vha->vp_idx) {ql_log (ql_log_warn, vha,0x6009 ,"Loop down - aborting ISP.\n" );
Greg Kroah-Hartman
maintainerPATCH 411/529 scsi: qla2xxx: Fix DMA-API call trace on NVMe LS requests
In reply to Greg Kroah-HartmanFrom: Arun Easi <[email protected]>
commit c75e6aef5039830cce5d4cf764dd204522f89e6b upstream.
The following message and call trace was seen with debug kernels:
DMA-API: qla2xxx 0000:41:00.0: device driver failed to check map error [device address=0x00000002a3ff38d8] [size=1024 bytes] [mapped as single]
WARNING: CPU: 0 PID: 2930 at kernel/dma/debug.c:1017 check_unmap+0xf42/0x1990 Call Trace: debug_dma_unmap_page+0xc9/0x100 qla_nvme_ls_unmap+0x141/0x210 [qla2xxx]
Remove DMA mapping from the driver altogether, as it is already done by FC layer. This prevents the warning.
--- drivers/scsi/qla2xxx/qla_nvme.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-)
drivers/scsi/qla2xxx/qla_nvme.c +1 -18
@@ -165,18 +165,6 @@ out:qla2xxx_rel_qpair_sp (sp->qpair, sp); } -static void qla_nvme_ls_unmap (struct srb *sp,struct nvmefc_ls_req *fd) -{ -if (sp->flags &SRB_DMA_VALID ) { -struct srb_iocb *nvme = &sp->u.iocb_cmd; -struct qla_hw_data *ha = sp->fcport->vha->hw; - -dma_unmap_single (&ha->pdev->dev, nvme->u.nvme.cmd_dma, - fd->rqstlen,DMA_TO_DEVICE ); - sp->flags &= ~SRB_DMA_VALID ; - } -} -static void qla_nvme_release_ls_cmd_kref (struct kref *kref) { struct srb *sp = container_of(kref, struct srb, cmd_kref);
@@ -194,7 +182,6 @@ static void qla_nvme_release_ls_cmd_kref fd = priv->fd; -qla_nvme_ls_unmap (sp, fd); fd->done (fd, priv->comp_status); out:qla2x00_rel_sp (sp);
@@ -336,13 +323,10 @@ static int qla_nvme_ls_req(struct nvme_f nvme->u.nvme.rsp_len = fd->rsplen; nvme->u.nvme.rsp_dma = fd->rspdma; nvme->u.nvme.timeout_sec = fd->timeout; - nvme->u.nvme.cmd_dma =dma_map_single (&ha->pdev->dev, fd->rqstaddr, - fd->rqstlen,DMA_TO_DEVICE ); + nvme->u.nvme.cmd_dma = fd->rqstdma;dma_sync_single_for_device (&ha->pdev->dev, nvme->u.nvme.cmd_dma, fd->rqstlen,DMA_TO_DEVICE ); - sp->flags |=SRB_DMA_VALID ; - rval =qla2x00_start_sp (sp);if (rval !=QLA_SUCCESS ) { ql_log(ql_log_warn, vha, 0x700e,
@@ -350,7 +334,6 @@ static int qla_nvme_ls_req(struct nvme_fwake_up (&sp->nvme_ls_waitq); sp->priv =NULL ; priv->sp =NULL ; -qla_nvme_ls_unmap (sp, fd);qla2x00_rel_sp (sp);return rval; }
Greg Kroah-Hartman
maintainerPATCH 412/529 scsi: qla2xxx: Fix erroneous link down
In reply to Greg Kroah-HartmanFrom: Quinn Tran <[email protected]>
commit 3fbc74feb642deb688cc97f76d40b7287ddd4cb1 upstream.
If after an adapter reset the appearance of link is not recovered, the devices are not rediscovered. This is result of a race condition between adapter reset (abort_isp) and the topology scan. During adapter reset, the ABORT_ISP_ACTIVE flag is set. Topology scan usually occurred after adapter reset. In this case, the topology scan came earlier than usual where it ran into problem due to ABORT_ISP_ACTIVE flag was still set.
kernel: qla2xxx [0000:13:00.0]-1005:1: Cmd 0x6a aborted with timeout since ISP Abort is pending
kernel: qla2xxx [0000:13:00.0]-28a0:1: MBX_GET_PORT_NAME failed, No FL Port.
kernel: qla2xxx [0000:13:00.0]-286b:1: qla2x00_configure_loop: exiting normally. local port wwpn 51402ec0123d9a80 id 012300)
kernel: qla2xxx [0000:13:00.0]-8017:1: ADAPTER RESET SUCCEEDED nexus=1:0:15.
Allow adapter reset to complete before any scan can start.
--- drivers/scsi/qla2xxx/qla_os.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/scsi/qla2xxx/qla_os.c +5 -2
@@ -6899,9 +6899,12 @@ qla2x00_do_dpc(void *data) } } loop_resync_check: -if (test_and_clear_bit (LOOP_RESYNC_NEEDED , +if (!qla2x00_reset_active (base_vha) && +test_and_clear_bit (LOOP_RESYNC_NEEDED , &base_vha->dpc_flags)) { - +/* +* Allow abort_isp to complete before moving on to scanning. +*/ ql_dbg (ql_dbg_dpc, base_vha,0x400f ,"Loop resync scheduled.\n" );
Greg Kroah-Hartman
maintainerPATCH 413/529 scsi: ses: Dont attach if enclosure has no components
In reply to Greg Kroah-HartmanFrom: James Bottomley <[email protected]>
commit 3fe97ff3d94934649abb0652028dd7296170c8d0 upstream.
An enclosure with no components can't usefully be operated by the driver (since effectively it has nothing to manage), so report the problem and don't attach. Not attaching also fixes an oops which could occur if the driver tries to manage a zero component enclosure.
[mkp: Switched to KERN_WARNING since this scenario is common]
--- drivers/scsi/ses.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/scsi/ses.c +6 -0
@@ -704,6 +704,12 @@ static int ses_intf_add(struct device *c type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE) components += type_ptr[1 ]; } + +if (components ==0 ) { +sdev_printk (KERN_WARNING , sdev,"enclosure has no enumerated components\n" ); + goto err_free; + } + ses_dev->page1 = buf; ses_dev->page1_len = len; buf =NULL ;
Greg Kroah-Hartman
maintainerPATCH 414/529 scsi: ses: Fix slab-out-of-bounds in ses_enclosure_data_process()
In reply to Greg Kroah-HartmanFrom: Tomas Henzl <[email protected]>
commit 9b4f5028e493cb353a5c8f5c45073eeea0303abd upstream.
A fix for:
BUG: KASAN: slab-out-of-bounds in ses_enclosure_data_process+0x949/0xe30 [ses] Read of size 1 at addr ffff88a1b043a451 by task systemd-udevd/3271
Checking after (and before in next loop) addl_desc_ptr[1] is sufficient, we expect the size to be sanitized before first access to addl_desc_ptr[1]. Make sure we don't walk beyond end of page.
--- drivers/scsi/ses.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/scsi/ses.c +4 -2
@@ -603,9 +603,11 @@ static void ses_enclosure_data_process(s/* these elements are optional */ type_ptr[0] == ENCLOSURE_COMPONENT_SCSI_TARGET_PORT || type_ptr[0] == ENCLOSURE_COMPONENT_SCSI_INITIATOR_PORT || - type_ptr[0] == ENCLOSURE_COMPONENT_CONTROLLER_ELECTRONICS)) + type_ptr[0] == ENCLOSURE_COMPONENT_CONTROLLER_ELECTRONICS)) { addl_desc_ptr += addl_desc_ptr[1 ] +2 ; - +if (addl_desc_ptr +1 >= ses_dev->page10 + ses_dev->page10_len) + addl_desc_ptr =NULL ; + } } }kfree (buf);
Greg Kroah-Hartman
maintainerPATCH 415/529 scsi: ses: Fix possible addl_desc_ptr out-of-bounds accesses
In reply to Greg Kroah-HartmanFrom: Tomas Henzl <[email protected]>
commit db95d4df71cb55506425b6e4a5f8d68e3a765b63 upstream.
Sanitize possible addl_desc_ptr out-of-bounds accesses in ses_enclosure_data_process().
--- drivers/scsi/ses.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-)
drivers/scsi/ses.c +26 -9
@@ -433,8 +433,8 @@ int ses_match_host(struct enclosure_devi }#endif /* 0 */ -static void ses_process_descriptor (struct enclosure_component *ecomp, -unsigned char *desc) +static int ses_process_descriptor (struct enclosure_component *ecomp, +unsigned char *desc,int max_desc_len) {int eip = desc[0 ] &0x10 ;int invalid = desc[0 ] &0x80 ;
@@ -445,22 +445,32 @@ static void ses_process_descriptor(strucunsigned char *d;if (invalid) -return ; +return 0 ;switch (proto) {case SCSI_PROTOCOL_FCP :if (eip) { +if (max_desc_len <=7 ) +return 1 ; d = desc +4 ; slot = d[3 ]; }break ;case SCSI_PROTOCOL_SAS : +if (eip) { +if (max_desc_len <=27 ) +return 1 ; d = desc +4 ; slot = d[3 ]; d = desc +8 ; - }else + }else { +if (max_desc_len <=23 ) +return 1 ; d = desc +4 ; + } + +/* only take the phy0 addr */ addr = (u64 )d[12 ] <<56 | (u64)d[13] << 48 |
@@ -477,6 +487,8 @@ static void ses_process_descriptor(struc } ecomp->slot = slot; scomp->addr = addr; + +return 0 ; }struct efd {
@@ -549,7 +561,7 @@ static void ses_enclosure_data_process(s/* skip past overall descriptor */ desc_ptr += len +4 ; } -if (ses_dev->page10) +if (ses_dev->page10 && ses_dev->page10_len >9 ) addl_desc_ptr = ses_dev->page10 +8 ; type_ptr = ses_dev->page1_types; components =0 ;
@@ -557,6 +569,7 @@ static void ses_enclosure_data_process(sfor (j =0 ; j < type_ptr[1 ]; j++) {char *name =NULL ;struct enclosure_component *ecomp; +int max_desc_len;if (desc_ptr) {if (desc_ptr >= buf + page7_len) {
@@ -583,10 +596,14 @@ static void ses_enclosure_data_process(s ecomp = &edev->component[components++];if (!IS_ERR (ecomp)) { -if (addl_desc_ptr) -ses_process_descriptor ( - ecomp, - addl_desc_ptr); +if (addl_desc_ptr) { + max_desc_len = ses_dev->page10_len - + (addl_desc_ptr - ses_dev->page10); +if (ses_process_descriptor (ecomp, + addl_desc_ptr, + max_desc_len)) + addl_desc_ptr =NULL ; + }if (create)enclosure_component_register ( ecomp);
Greg Kroah-Hartman
maintainerPATCH 416/529 scsi: ses: Fix possible desc_ptr out-of-bounds accesses
In reply to Greg Kroah-HartmanFrom: Tomas Henzl <[email protected]>
commit 801ab13d50cf3d26170ee073ea8bb4eececb76ab upstream.
Sanitize possible desc_ptr out-of-bounds accesses in ses_enclosure_data_process().
--- drivers/scsi/ses.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
drivers/scsi/ses.c +9 -5
@@ -572,15 +572,19 @@ static void ses_enclosure_data_process(sint max_desc_len;if (desc_ptr) { -if (desc_ptr >= buf + page7_len) { +if (desc_ptr +3 >= buf + page7_len) { desc_ptr =NULL ; }else { len = (desc_ptr[2 ] <<8 ) + desc_ptr[3 ]; desc_ptr +=4 ; -/* Add trailing zero - pushes into -* reserved space */ - desc_ptr[len] ='\0' ; - name = desc_ptr; +if (desc_ptr + len > buf + page7_len) + desc_ptr =NULL ; +else { +/* Add trailing zero - pushes into +* reserved space */ + desc_ptr[len] ='\0' ; + name = desc_ptr; + } } } if (type_ptr[0] == ENCLOSURE_COMPONENT_DEVICE ||
Greg Kroah-Hartman
maintainerPATCH 417/529 scsi: ses: Fix slab-out-of-bounds in ses_intf_remove()
In reply to Greg Kroah-HartmanFrom: Tomas Henzl <[email protected]>
commit 578797f0c8cbc2e3ec5fc0dab87087b4c7073686 upstream.
A fix for:
BUG: KASAN: slab-out-of-bounds in ses_intf_remove+0x23f/0x270 [ses] Read of size 8 at addr ffff88a10d32e5d8 by task rmmod/12013
When edev->components is zero, accessing edev->component[0] members is wrong.
--- drivers/scsi/ses.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/scsi/ses.c +2 -1
@@ -856,7 +856,8 @@ static void ses_intf_remove_enclosure(stkfree (ses_dev->page2);kfree (ses_dev); -kfree (edev->component[0 ].scratch); +if (edev->components) +kfree (edev->component[0 ].scratch);put_device (&edev->edev);enclosure_unregister (edev);
Greg Kroah-Hartman
maintainerPATCH 418/529 riscv: jump_label: Fixup unaligned arch_static_branch function
In reply to Greg Kroah-HartmanFrom: Andy Chiu <[email protected]>
commit 9ddfc3cd806081ce1f6c9c2f988cbb031f35d28f upstream.
Runtime code patching must be done at a naturally aligned address, or we may execute on a partial instruction.
We have encountered problems traced back to static jump functions during the test. We switched the tracer randomly for every 1~5 seconds on a dual-core QEMU setup and found the kernel sucking at a static branch where it jumps to itself.
The reason is that the static branch was 2-byte but not 4-byte aligned. Then, the kernel would patch the instruction, either J or NOP, with two half-word stores if the machine does not have efficient unaligned accesses. Thus, moments exist where half of the NOP mixes with the other half of the J when transitioning the branch. In our particular case, on a little-endian machine, the upper half of the NOP was mixed with the lower part of the J when enabling the branch, resulting in a jump that jumped to itself. Conversely, it would result in a HINT instruction when disabling the branch, but it might not be observable.
ARM64 does not have this problem since all instructions must be 4-byte aligned.
--- arch/riscv/include/asm/jump_label.h | 2 ++ 1 file changed, 2 insertions(+)
arch/riscv/include/asm/jump_label.h +2 -0
@@ -18,6 +18,7 @@ static __always_inline bool arch_static_ bool branch) {asm_volatile_goto ( +" .align 2 \n\t" " .option push \n\t" " .option norelax \n\t" " .option norvc \n\t"
@@ -39,6 +40,7 @@ static __always_inline bool arch_static_ bool branch) {asm_volatile_goto ( +" .align 2 \n\t" " .option push \n\t" " .option norelax \n\t" " .option norvc \n\t"
Greg Kroah-Hartman
maintainerPATCH 419/529 PCI/PM: Observe reset delay irrespective of bridge_d3
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit 8ef0217227b42e2c34a18de316cee3da16c9bf1e upstream.
If a PCI bridge is suspended to D3cold upon entering system sleep, resuming it entails a Fundamental Reset per PCIe r6.0 sec 5.8.
The delay prescribed after a Fundamental Reset in PCIe r6.0 sec 6.6.1 is sought to be observed by:
pci_pm_resume_noirq()
pci_pm_bridge_power_up_actions()
pci_bridge_wait_for_secondary_bus()
However, pci_bridge_wait_for_secondary_bus() bails out if the bridge_d3 flag is not set. That flag indicates whether a bridge is allowed to suspend to D3cold at *runtime*.
Hence *no* delay is observed on resume from system sleep if runtime D3cold is forbidden. That doesn't make any sense, so drop the bridge_d3 check from pci_bridge_wait_for_secondary_bus().
The purpose of the bridge_d3 check was probably to avoid delays if a bridge remained in D0 during suspend. However the sole caller of pci_bridge_wait_for_secondary_bus(), pci_pm_bridge_power_up_actions(), is only invoked if the previous power state was D3cold. Hence the additional bridge_d3 check seems superfluous.
--- drivers/pci/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pci/pci.c +1 -1
@@ -4808,7 +4808,7 @@ void pci_bridge_wait_for_secondary_bus(sif (pci_dev_is_disconnected (dev))return ; -if (!pci_is_bridge (dev) || !dev->bridge_d3) +if (!pci_is_bridge (dev))return ;down_read (&pci_bus_sem);
Greg Kroah-Hartman
maintainerPATCH 420/529 PCI: hotplug: Allow marking devices as disconnected during bind/unbind
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit 74ff8864cc842be994853095dba6db48e716400a upstream.
On surprise removal, pciehp_unconfigure_device() and acpiphp's trim_stale_devices() call pci_dev_set_disconnected() to mark removed devices as permanently offline. Thereby, the PCI core and drivers know to skip device accesses.
However pci_dev_set_disconnected() takes the device_lock and thus waits for a concurrent driver bind or unbind to complete. As a result, the driver's ->probe and ->remove hooks have no chance to learn that the device is gone.
That doesn't make any sense, so drop the device_lock and instead use atomic xchg() and cmpxchg() operations to update the device state.
As a byproduct, an AB-BA deadlock reported by Anatoli is fixed which occurs on surprise removal with AER concurrently performing a bus reset.
AER bus reset:
INFO: task irq/26-aerdrv:95 blocked for more than 120 seconds. Tainted: G W 6.2.0-rc3-custom-norework-jan11+ schedule rwsem_down_write_slowpath down_write_nested pciehp_reset_slot # acquires reset_lock pci_reset_hotplug_slot pci_slot_reset # acquires device_lock pci_bus_error_reset aer_root_reset pcie_do_recovery aer_process_err_devices aer_isr
pciehp surprise removal:
INFO: task irq/26-pciehp:96 blocked for more than 120 seconds. Tainted: G W 6.2.0-rc3-custom-norework-jan11+ schedule_preempt_disabled __mutex_lock mutex_lock_nested pci_dev_set_disconnected # acquires device_lock pci_walk_bus pciehp_unconfigure_device pciehp_disable_slot pciehp_handle_presence_or_link_change pciehp_ist # acquires reset_lock
--- drivers/pci/pci.h | 43 +++++++++++++------------------------------ 1 file changed, 13 insertions(+), 30 deletions(-)
drivers/pci/pci.h +13 -30
@@ -351,53 +351,36 @@ struct pci_sriov {* @dev - pci device to set new error_state * @new - the state we want dev to be in * -* Must be called with device_lock held. +* If the device is experiencing perm_failure, it has to remain in that state. +* Any other transition is allowed. * * Returns true if state has been changed to the requested state. */ static inline bool pci_dev_set_io_state (struct pci_dev *dev,pci_channel_state_t new) { -bool changed = false; +pci_channel_state_t old; -device_lock_assert (&dev->dev);switch (new) {case pci_channel_io_perm_failure: -switch (dev->error_state) { -case pci_channel_io_frozen: -case pci_channel_io_normal: -case pci_channel_io_perm_failure: - changed = true; -break ; - } -break ; +xchg (&dev->error_state, pci_channel_io_perm_failure); +return true;case pci_channel_io_frozen: -switch (dev->error_state) { -case pci_channel_io_frozen: -case pci_channel_io_normal: - changed = true; -break ; - } -break ; + old =cmpxchg (&dev->error_state, pci_channel_io_normal, + pci_channel_io_frozen); +return old != pci_channel_io_perm_failure;case pci_channel_io_normal: -switch (dev->error_state) { -case pci_channel_io_frozen: -case pci_channel_io_normal: - changed = true; -break ; - } -break ; + old =cmpxchg (&dev->error_state, pci_channel_io_frozen, + pci_channel_io_normal); +return old != pci_channel_io_perm_failure; +default : +return false; } -if (changed) - dev->error_state = new; -return changed; }static inline int pci_dev_set_disconnected (struct pci_dev *dev,void *unused) { -device_lock (&dev->dev);pci_dev_set_io_state (dev, pci_channel_io_perm_failure); -device_unlock (&dev->dev);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 421/529 PCI: Avoid FLR for AMD FCH AHCI adapters
In reply to Greg Kroah-HartmanFrom: Damien Le Moal <[email protected]>
commit 63ba51db24ed1b8f8088a897290eb6c036c5435d upstream.
PCI passthrough to VMs does not work with AMD FCH AHCI adapters: the guest OS fails to correctly probe devices attached to the controller due to FIS communication failures:
ata4: softreset failed (1st FIS failed)
...
ata4.00: qc timeout after 5000 msecs (cmd 0xec) ata4.00: failed to IDENTIFY (I/O error, err_mask=0x4)
Forcing the "bus" reset method before unbinding & binding the adapter to the vfio-pci driver solves this issue, e.g.:
echo "bus" > /sys/bus/pci/devices/<ID>/reset_method
gives a working guest OS, indicating that the default FLR reset method doesn't work correctly.
Apply quirk_no_flr() to AMD FCH AHCI devices to work around this issue.
--- drivers/pci/quirks.c | 1 + 1 file changed, 1 insertion(+)
drivers/pci/quirks.c +1 -0
@@ -5302,6 +5302,7 @@ static void quirk_no_flr(struct pci_devDECLARE_PCI_FIXUP_EARLY (PCI_VENDOR_ID_AMD ,0x1487 , quirk_no_flr);DECLARE_PCI_FIXUP_EARLY (PCI_VENDOR_ID_AMD ,0x148c , quirk_no_flr);DECLARE_PCI_FIXUP_EARLY (PCI_VENDOR_ID_AMD ,0x149c , quirk_no_flr); +DECLARE_PCI_FIXUP_EARLY (PCI_VENDOR_ID_AMD ,0x7901 , quirk_no_flr);DECLARE_PCI_FIXUP_EARLY (PCI_VENDOR_ID_INTEL ,0x1502 , quirk_no_flr);DECLARE_PCI_FIXUP_EARLY (PCI_VENDOR_ID_INTEL ,0x1503 , quirk_no_flr);
Greg Kroah-Hartman
maintainerPATCH 422/529 vfio/type1: prevent underflow of locked_vm via exec()
In reply to Greg Kroah-HartmanFrom: Steve Sistare <[email protected]>
commit 046eca5018f8a5dd1dc2cedf87fb5843b9ea3026 upstream.
When a vfio container is preserved across exec, the task does not change, but it gets a new mm with locked_vm=0, and loses the count from existing dma mappings. If the user later unmaps a dma mapping, locked_vm underflows to a large unsigned value, and a subsequent dma map request fails with ENOMEM in __account_locked_vm.
To avoid underflow, grab and save the mm at the time a dma is mapped. Use that mm when adjusting locked_vm, rather than re-acquiring the saved task's mm, which may have changed. If the saved mm is dead, do nothing.
locked_vm is incremented for existing mappings in a subsequent patch.
--- drivers/vfio/vfio_iommu_type1.c | 41 +++++++++++++--------------------------- 1 file changed, 14 insertions(+), 27 deletions(-)
drivers/vfio/vfio_iommu_type1.c +14 -27
@@ -96,6 +96,7 @@ struct vfio_dma {struct task_struct *task;struct rb_root pfn_list;/* Ex-user pinned pfn list */ unsigned long *bitmap; +struct mm_struct *mm; };struct vfio_batch {
@@ -391,8 +392,8 @@ static int vfio_lock_acct(struct vfio_dmif (!npage)return 0 ; - mm = async ?get_task_mm (dma->task) : dma->task->mm; -if (!mm) + mm = dma->mm; +if (async && !mmget_not_zero (mm))return -ESRCH ;/* process exited */ ret =mmap_write_lock_killable (mm);
@@ -666,8 +667,8 @@ static int vfio_pin_page_external(structstruct mm_struct *mm;int ret; - mm =get_task_mm (dma->task); -if (!mm) + mm = dma->mm; +if (!mmget_not_zero (mm))return -ENODEV ; ret =vaddr_get_pfns (mm, vaddr,1 , dma->prot, pfn_base, pages);
@@ -677,7 +678,7 @@ static int vfio_pin_page_external(struct ret =0 ;if (do_accounting && !is_invalid_reserved_pfn (*pfn_base)) { - ret =vfio_lock_acct (dma,1 , true); + ret =vfio_lock_acct (dma,1 , false);if (ret) {put_pfn (*pfn_base, dma->prot);if (ret == -ENOMEM )
@@ -1031,6 +1032,7 @@ static void vfio_remove_dma(struct vfio_vfio_unmap_unpin (iommu, dma, true);vfio_unlink_dma (iommu, dma);put_task_struct (dma->task); +mmdrop (dma->mm);vfio_dma_bitmap_free (dma);kfree (dma); iommu->dma_avail++;
@@ -1452,29 +1454,15 @@ static int vfio_dma_do_map(struct vfio_i* against the locked memory limit and we need to be able to do both * outside of this call path as pinning can be asynchronous via the * external interfaces for mdev devices. RLIMIT_MEMLOCK requires a -* task_struct and VM locked pages requires an mm_struct, however -* holding an indefinite mm reference is not recommended, therefore we -* only hold a reference to a task. We could hold a reference to -* current, however QEMU uses this call path through vCPU threads, -* which can be killed resulting in a NULL mm and failure in the unmap -* path when called via a different thread. Avoid this problem by -* using the group_leader as threads within the same group require -* both CLONE_THREAD and CLONE_VM and will therefore use the same -* mm_struct. -* -* Previously we also used the task for testing CAP_IPC_LOCK at the -* time of pinning and accounting, however has_capability() makes use -* of real_cred, a copy-on-write field, so we can't guarantee that it -* matches group_leader, or in fact that it might not change by the -* time it's evaluated. If a process were to call MAP_DMA with -* CAP_IPC_LOCK but later drop it, it doesn't make sense that they -* possibly see different results for an iommu_mapped vfio_dma vs -* externally mapped. Therefore track CAP_IPC_LOCK in vfio_dma at the -* time of calling MAP_DMA. +* task_struct. Save the group_leader so that all DMA tracking uses +* the same task, to make debugging easier. VM locked pages requires +* an mm_struct, so grab the mm in case the task dies. */ get_task_struct (current->group_leader); dma->task = current->group_leader; dma->lock_cap =capable (CAP_IPC_LOCK ); + dma->mm = current->mm; +mmgrab (dma->mm); dma->pfn_list =RB_ROOT ;
@@ -2998,9 +2986,8 @@ static int vfio_iommu_type1_dma_rw_chunk !(dma->prot & IOMMU_READ))return -EPERM ; - mm =get_task_mm (dma->task); - -if (!mm) + mm = dma->mm; +if (!mmget_not_zero (mm))return -EPERM ;if (kthread)
Greg Kroah-Hartman
maintainerPATCH 423/529 drm/i915/quirks: Add inverted backlight quirk for HP 14-r206nv
In reply to Greg Kroah-HartmanFrom: Mavroudis Chatzilaridis <[email protected]>
commit 5e438bf7f9a1705ebcae5fa89cdbfbc6932a7871 upstream.
This laptop uses inverted backlight PWM. Thus, without this quirk, backlight brightness decreases as the brightness value increases and vice versa.
--- drivers/gpu/drm/i915/display/intel_quirks.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/gpu/drm/i915/display/intel_quirks.c +2 -0
@@ -159,6 +159,8 @@ static struct intel_quirk intel_quirks[]/* ECS Liva Q2 */ { 0x3185, 0x1019, 0xa94d, quirk_increase_ddi_disabled_time }, { 0x3184, 0x1019, 0xa94d, quirk_increase_ddi_disabled_time }, +/* HP Notebook - 14-r206nv */ + { 0x0f31, 0x103c, 0x220f, quirk_invert_brightness }, };void intel_init_quirks (struct drm_i915_private *i915)
Greg Kroah-Hartman
maintainerPATCH 424/529 drm/radeon: Fix eDP for single-display iMac11,2
In reply to Greg Kroah-HartmanFrom: Mark Hawrylak <[email protected]>
commit 05eacc198c68cbb35a7281ce4011f8899ee1cfb8 upstream.
Apple iMac11,2 (mid 2010) also with Radeon HD-4670 that has the same issue as iMac10,1 (late 2009) where the internal eDP panel stays dark on driver load. This patch treats iMac11,2 the same as iMac10,1, so the eDP panel stays active.
Additional steps:
Kernel boot parameter radeon.nomodeset=0 required to keep the eDP panel active.
This patch is an extension of
commit 564d8a2cf3ab ("drm/radeon: Fix eDP for single-display iMac10,1 (v2)")
--- drivers/gpu/drm/radeon/atombios_encoders.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/gpu/drm/radeon/atombios_encoders.c +3 -2
@@ -2191,11 +2191,12 @@ int radeon_atom_pick_dig_encoder(struct/* * On DCE32 any encoder can drive any block so usually just use crtc id, -* but Apple thinks different at least on iMac10,1, so there use linkb, +* but Apple thinks different at least on iMac10,1 and iMac11,2, so there use linkb, * otherwise the internal eDP panel will stay dark. */ if (ASIC_IS_DCE32 (rdev)) { -if (dmi_match (DMI_PRODUCT_NAME ,"iMac10,1" )) +if (dmi_match (DMI_PRODUCT_NAME ,"iMac10,1" ) || +dmi_match (DMI_PRODUCT_NAME ,"iMac11,2" )) enc_idx = (dig->linkb) ?1 :0 ;else enc_idx = radeon_crtc->crtc_id;
Greg Kroah-Hartman
maintainerPATCH 425/529 drm/edid: fix AVI infoframe aspect ratio handling
In reply to Greg Kroah-HartmanFrom: Jani Nikula <[email protected]>
commit 1cbc1f0d324ba6c4d1b10ac6362b5e0b029f63d5 upstream.
We try to avoid sending VICs defined in the later specs in AVI infoframes to sinks that conform to the earlier specs, to not upset them, and use 0 for the VIC instead. However, we do this detection and conversion to 0 too early, as we'll need the actual VIC to figure out the aspect ratio.
In particular, for a mode with 64:27 aspect ratio, 0 for VIC fails the AVI infoframe generation altogether with -EINVAL.
Separate the VIC lookup from the "filtering", and postpone the filtering, to use the proper VIC for aspect ratio handling, and the 0 VIC for the infoframe video code as needed.
--- drivers/gpu/drm/drm_edid.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-)
drivers/gpu/drm/drm_edid.c +12 -9
@@ -5560,8 +5560,6 @@ static u8 drm_mode_hdmi_vic(const structstatic u8 drm_mode_cea_vic (const struct drm_connector *connector,const struct drm_display_mode *mode) { -u8 vic; -/* * HDMI spec says if a mode is found in HDMI 1.4b 4K modes * we should send its VIC in vendor infoframes, else send the
@@ -5571,13 +5569,18 @@ static u8 drm_mode_cea_vic(const structif (drm_mode_hdmi_vic (connector, mode))return 0 ; - vic =drm_match_cea_mode (mode); +return drm_match_cea_mode (mode); +} -/* -* HDMI 1.4 VIC range: 1 <= VIC <= 64 (CEA-861-D) but -* HDMI 2.0 VIC range: 1 <= VIC <= 107 (CEA-861-F). So we -* have to make sure we dont break HDMI 1.4 sinks. -*/ +/* +* Avoid sending VICs defined in HDMI 2.0 in AVI infoframes to sinks that +* conform to HDMI 1.4. +* +* HDMI 1.4 (CTA-861-D) VIC range: [1..64] +* HDMI 2.0 (CTA-861-F) VIC range: [1..107] +*/ +static u8 vic_for_avi_infoframe (const struct drm_connector *connector,u8 vic) +{if (!is_hdmi2_sink (connector) && vic >64 )return 0 ;
@@ -5653,7 +5656,7 @@ drm_hdmi_avi_infoframe_from_display_mode picture_aspect =HDMI_PICTURE_ASPECT_NONE ; } - frame->video_code = vic; + frame->video_code =vic_for_avi_infoframe (connector, vic); frame->picture_aspect = picture_aspect; frame->active_aspect =HDMI_ACTIVE_ASPECT_PICTURE ; frame->scan_mode =HDMI_SCAN_MODE_UNDERSCAN ;
Greg Kroah-Hartman
maintainerPATCH 426/529 arm64: dts: qcom: ipq8074: fix Gen2 PCIe QMP PHY
In reply to Greg Kroah-HartmanFrom: Robert Marko <[email protected]>
commit 100d9c94ccf15b02742c326cd04f422ab729153b upstream.
Serdes register space sizes are incorrect, update them to match the actual sizes from downstream QCA 5.4 kernel.
--- arch/arm64/boot/dts/qcom/ipq8074.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm64/boot/dts/qcom/ipq8074.dtsi +2 -2
@@ -213,9 +213,9 @@ status = "disabled"; pcie_phy1: phy@8e200 { - reg = <0x8e200 0x16c>, + reg = <0x8e200 0x130>, <0x8e400 0x200>, - <0x8e800 0x4f4>; + <0x8e800 0x1f8>; #phy-cells = <0>; #clock-cells = <0>; clocks = <&gcc GCC_PCIE1_PIPE_CLK>;
Greg Kroah-Hartman
maintainerPATCH 427/529 wifi: ath9k: use proper statements in conditionals
In reply to Greg Kroah-HartmanFrom: Arnd Bergmann <[email protected]>
commit b7dc753fe33a707379e2254317794a4dad6c0fe2 upstream.
A previous cleanup patch accidentally broke some conditional expressions by replacing the safe "do {} while (0)" constructs with empty macros. gcc points this out when extra warnings are enabled:
drivers/net/wireless/ath/ath9k/hif_usb.c: In function 'ath9k_skb_queue_complete':drivers/net/wireless/ath/ath9k/hif_usb.c:251:57: error: suggest braces around empty body in an 'else' statement [-Werror=empty-body]
251 | TX_STAT_INC(hif_dev, skb_failed);
Make both sets of macros proper expressions again.
--- drivers/net/wireless/ath/ath9k/htc.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
drivers/net/wireless/ath/ath9k/htc.h +7 -7
@@ -327,9 +327,9 @@ static inline struct ath9k_htc_tx_ctl *H }#ifdef CONFIG_ATH9K_HTC_DEBUGFS -#define __STAT_SAFE (hif_dev, expr) ((hif_dev)->htc_handle->drv_priv ? (expr) : 0) -#define CAB_STAT_INC (priv) ((priv)->debug.tx_stats.cab_queued++) -#define TX_QSTAT_INC (priv, q) ((priv)->debug.tx_stats.queue_stats[q]++) +#define __STAT_SAFE (hif_dev, expr) do { ((hif_dev)->htc_handle->drv_priv ? (expr) : 0); } while (0) +#define CAB_STAT_INC (priv) do { ((priv)->debug.tx_stats.cab_queued++); } while (0) +#define TX_QSTAT_INC (priv, q) do { ((priv)->debug.tx_stats.queue_stats[q]++); } while (0)#define TX_STAT_INC (hif_dev, c) \ __STAT_SAFE((hif_dev), (hif_dev)->htc_handle->drv_priv->debug.tx_stats.c++)
@@ -378,10 +378,10 @@ void ath9k_htc_get_et_stats(struct ieee8 struct ethtool_stats *stats, u64 *data);#else -#define TX_STAT_INC (hif_dev, c) -#define TX_STAT_ADD (hif_dev, c, a) -#define RX_STAT_INC (hif_dev, c) -#define RX_STAT_ADD (hif_dev, c, a) +#define TX_STAT_INC (hif_dev, c) do { } while (0) +#define TX_STAT_ADD (hif_dev, c, a) do { } while (0) +#define RX_STAT_INC (hif_dev, c) do { } while (0) +#define RX_STAT_ADD (hif_dev, c, a) do { } while (0)#define CAB_STAT_INC (priv)#define TX_QSTAT_INC (priv, c)
Greg Kroah-Hartman
maintainerPATCH 428/529 pinctrl: rockchip: fix mux route data for rk3568
In reply to Greg Kroah-HartmanFrom: Jonas Karlman <[email protected]>
commit 431d1531466033909d2e8c754a7dc3704b70843f upstream.
IO mux selection is configured in PMU_GRF_SOC_CON4 and GRF_IOFUNC_SEL0-5 regs on RK3568. pwm0-2 is configured in PMU_GRF reg and the rest is configured in GRF_IOFUNC regs according to TRM [1].
Update mux route data to reflect this and use proper detection pin for UART1 IO mux M1.
This fixes HDMITX IO mux M1 selection and makes it possible to enable HDMI CEC on my Radxa ROCK 3 Model A v1.31 board.
[1] http://opensource.rock-chips.com/images/2/26/Rockchip_RK3568_TRM_Part1_V1.3-20220930P.PDF
--- drivers/pinctrl/pinctrl-rockchip.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
drivers/pinctrl/pinctrl-rockchip.c +10 -10
@@ -954,19 +954,19 @@ static struct rockchip_mux_route_data rkRK_MUXROUTE_PMU (0 ,RK_PB5 ,4 ,0x0110 ,WRITE_MASK_VAL (3 ,2 ,1 )),/* PWM1 IO mux M1 */ RK_MUXROUTE_PMU (0 ,RK_PC1 ,1 ,0x0110 ,WRITE_MASK_VAL (5 ,4 ,0 )),/* PWM2 IO mux M0 */ RK_MUXROUTE_PMU (0 ,RK_PB6 ,4 ,0x0110 ,WRITE_MASK_VAL (5 ,4 ,1 )),/* PWM2 IO mux M1 */ -RK_MUXROUTE_PMU (0 ,RK_PB3 ,2 ,0x0300 ,WRITE_MASK_VAL (0 ,0 ,0 )),/* CAN0 IO mux M0 */ +RK_MUXROUTE_GRF (0 ,RK_PB3 ,2 ,0x0300 ,WRITE_MASK_VAL (0 ,0 ,0 )),/* CAN0 IO mux M0 */ RK_MUXROUTE_GRF (2 ,RK_PA1 ,4 ,0x0300 ,WRITE_MASK_VAL (0 ,0 ,1 )),/* CAN0 IO mux M1 */ RK_MUXROUTE_GRF (1 ,RK_PA1 ,3 ,0x0300 ,WRITE_MASK_VAL (2 ,2 ,0 )),/* CAN1 IO mux M0 */ RK_MUXROUTE_GRF (4 ,RK_PC3 ,3 ,0x0300 ,WRITE_MASK_VAL (2 ,2 ,1 )),/* CAN1 IO mux M1 */ RK_MUXROUTE_GRF (4 ,RK_PB5 ,3 ,0x0300 ,WRITE_MASK_VAL (4 ,4 ,0 )),/* CAN2 IO mux M0 */ RK_MUXROUTE_GRF (2 ,RK_PB2 ,4 ,0x0300 ,WRITE_MASK_VAL (4 ,4 ,1 )),/* CAN2 IO mux M1 */ RK_MUXROUTE_GRF (4 ,RK_PC4 ,1 ,0x0300 ,WRITE_MASK_VAL (6 ,6 ,0 )),/* HPDIN IO mux M0 */ -RK_MUXROUTE_PMU (0 ,RK_PC2 ,2 ,0x0300 ,WRITE_MASK_VAL (6 ,6 ,1 )),/* HPDIN IO mux M1 */ +RK_MUXROUTE_GRF (0 ,RK_PC2 ,2 ,0x0300 ,WRITE_MASK_VAL (6 ,6 ,1 )),/* HPDIN IO mux M1 */ RK_MUXROUTE_GRF (3 ,RK_PB1 ,3 ,0x0300 ,WRITE_MASK_VAL (8 ,8 ,0 )),/* GMAC1 IO mux M0 */ RK_MUXROUTE_GRF (4 ,RK_PA7 ,3 ,0x0300 ,WRITE_MASK_VAL (8 ,8 ,1 )),/* GMAC1 IO mux M1 */ RK_MUXROUTE_GRF (4 ,RK_PD1 ,1 ,0x0300 ,WRITE_MASK_VAL (10 ,10 ,0 )),/* HDMITX IO mux M0 */ -RK_MUXROUTE_PMU (0 ,RK_PC7 ,1 ,0x0300 ,WRITE_MASK_VAL (10 ,10 ,1 )),/* HDMITX IO mux M1 */ -RK_MUXROUTE_PMU (0 ,RK_PB6 ,1 ,0x0300 ,WRITE_MASK_VAL (14 ,14 ,0 )),/* I2C2 IO mux M0 */ +RK_MUXROUTE_GRF (0 ,RK_PC7 ,1 ,0x0300 ,WRITE_MASK_VAL (10 ,10 ,1 )),/* HDMITX IO mux M1 */ +RK_MUXROUTE_GRF (0 ,RK_PB6 ,1 ,0x0300 ,WRITE_MASK_VAL (14 ,14 ,0 )),/* I2C2 IO mux M0 */ RK_MUXROUTE_GRF (4 ,RK_PB4 ,1 ,0x0300 ,WRITE_MASK_VAL (14 ,14 ,1 )),/* I2C2 IO mux M1 */ RK_MUXROUTE_GRF (1 ,RK_PA0 ,1 ,0x0304 ,WRITE_MASK_VAL (0 ,0 ,0 )),/* I2C3 IO mux M0 */ RK_MUXROUTE_GRF(3, RK_PB6, 4, 0x0304, WRITE_MASK_VAL(0, 0, 1)), /* I2C3 IO mux M1 */
@@ -992,7 +992,7 @@ static struct rockchip_mux_route_data rkRK_MUXROUTE_GRF (4 ,RK_PC3 ,1 ,0x0308 ,WRITE_MASK_VAL (12 ,12 ,1 )),/* PWM15 IO mux M1 */ RK_MUXROUTE_GRF (3 ,RK_PD2 ,3 ,0x0308 ,WRITE_MASK_VAL (14 ,14 ,0 )),/* SDMMC2 IO mux M0 */ RK_MUXROUTE_GRF (3 ,RK_PA5 ,5 ,0x0308 ,WRITE_MASK_VAL (14 ,14 ,1 )),/* SDMMC2 IO mux M1 */ -RK_MUXROUTE_PMU (0 ,RK_PB5 ,2 ,0x030c ,WRITE_MASK_VAL (0 ,0 ,0 )),/* SPI0 IO mux M0 */ +RK_MUXROUTE_GRF (0 ,RK_PB5 ,2 ,0x030c ,WRITE_MASK_VAL (0 ,0 ,0 )),/* SPI0 IO mux M0 */ RK_MUXROUTE_GRF (2 ,RK_PD3 ,3 ,0x030c ,WRITE_MASK_VAL (0 ,0 ,1 )),/* SPI0 IO mux M1 */ RK_MUXROUTE_GRF (2 ,RK_PB5 ,3 ,0x030c ,WRITE_MASK_VAL (2 ,2 ,0 )),/* SPI1 IO mux M0 */ RK_MUXROUTE_GRF(3, RK_PC3, 3, 0x030c, WRITE_MASK_VAL(2, 2, 1)), /* SPI1 IO mux M1 */
@@ -1001,8 +1001,8 @@ static struct rockchip_mux_route_data rkRK_MUXROUTE_GRF (4 ,RK_PB3 ,4 ,0x030c ,WRITE_MASK_VAL (6 ,6 ,0 )),/* SPI3 IO mux M0 */ RK_MUXROUTE_GRF (4 ,RK_PC2 ,2 ,0x030c ,WRITE_MASK_VAL (6 ,6 ,1 )),/* SPI3 IO mux M1 */ RK_MUXROUTE_GRF (2 ,RK_PB4 ,2 ,0x030c ,WRITE_MASK_VAL (8 ,8 ,0 )),/* UART1 IO mux M0 */ -RK_MUXROUTE_PMU (0 ,RK_PD1 ,1 ,0x030c ,WRITE_MASK_VAL (8 ,8 ,1 )),/* UART1 IO mux M1 */ -RK_MUXROUTE_PMU (0 ,RK_PD1 ,1 ,0x030c ,WRITE_MASK_VAL (10 ,10 ,0 )),/* UART2 IO mux M0 */ +RK_MUXROUTE_GRF (3 ,RK_PD6 ,4 ,0x030c ,WRITE_MASK_VAL (8 ,8 ,1 )),/* UART1 IO mux M1 */ +RK_MUXROUTE_GRF (0 ,RK_PD1 ,1 ,0x030c ,WRITE_MASK_VAL (10 ,10 ,0 )),/* UART2 IO mux M0 */ RK_MUXROUTE_GRF (1 ,RK_PD5 ,2 ,0x030c ,WRITE_MASK_VAL (10 ,10 ,1 )),/* UART2 IO mux M1 */ RK_MUXROUTE_GRF (1 ,RK_PA1 ,2 ,0x030c ,WRITE_MASK_VAL (12 ,12 ,0 )),/* UART3 IO mux M0 */ RK_MUXROUTE_GRF(3, RK_PB7, 4, 0x030c, WRITE_MASK_VAL(12, 12, 1)), /* UART3 IO mux M1 */
@@ -1032,13 +1032,13 @@ static struct rockchip_mux_route_data rkRK_MUXROUTE_GRF (3 ,RK_PD6 ,5 ,0x0314 ,WRITE_MASK_VAL (1 ,0 ,1 )),/* PDM IO mux M1 */ RK_MUXROUTE_GRF (4 ,RK_PA0 ,4 ,0x0314 ,WRITE_MASK_VAL (1 ,0 ,1 )),/* PDM IO mux M1 */ RK_MUXROUTE_GRF (3 ,RK_PC4 ,5 ,0x0314 ,WRITE_MASK_VAL (1 ,0 ,2 )),/* PDM IO mux M2 */ -RK_MUXROUTE_PMU (0 ,RK_PA5 ,3 ,0x0314 ,WRITE_MASK_VAL (3 ,2 ,0 )),/* PCIE20 IO mux M0 */ +RK_MUXROUTE_GRF (0 ,RK_PA5 ,3 ,0x0314 ,WRITE_MASK_VAL (3 ,2 ,0 )),/* PCIE20 IO mux M0 */ RK_MUXROUTE_GRF (2 ,RK_PD0 ,4 ,0x0314 ,WRITE_MASK_VAL (3 ,2 ,1 )),/* PCIE20 IO mux M1 */ RK_MUXROUTE_GRF (1 ,RK_PB0 ,4 ,0x0314 ,WRITE_MASK_VAL (3 ,2 ,2 )),/* PCIE20 IO mux M2 */ -RK_MUXROUTE_PMU (0 ,RK_PA4 ,3 ,0x0314 ,WRITE_MASK_VAL (5 ,4 ,0 )),/* PCIE30X1 IO mux M0 */ +RK_MUXROUTE_GRF (0 ,RK_PA4 ,3 ,0x0314 ,WRITE_MASK_VAL (5 ,4 ,0 )),/* PCIE30X1 IO mux M0 */ RK_MUXROUTE_GRF (2 ,RK_PD2 ,4 ,0x0314 ,WRITE_MASK_VAL (5 ,4 ,1 )),/* PCIE30X1 IO mux M1 */ RK_MUXROUTE_GRF (1 ,RK_PA5 ,4 ,0x0314 ,WRITE_MASK_VAL (5 ,4 ,2 )),/* PCIE30X1 IO mux M2 */ -RK_MUXROUTE_PMU (0 ,RK_PA6 ,2 ,0x0314 ,WRITE_MASK_VAL (7 ,6 ,0 )),/* PCIE30X2 IO mux M0 */ +RK_MUXROUTE_GRF (0 ,RK_PA6 ,2 ,0x0314 ,WRITE_MASK_VAL (7 ,6 ,0 )),/* PCIE30X2 IO mux M0 */ RK_MUXROUTE_GRF (2 ,RK_PD4 ,4 ,0x0314 ,WRITE_MASK_VAL (7 ,6 ,1 )),/* PCIE30X2 IO mux M1 */ RK_MUXROUTE_GRF(4, RK_PC2, 4, 0x0314, WRITE_MASK_VAL(7, 6, 2)), /* PCIE30X2 IO mux M2 */ };
Greg Kroah-Hartman
maintainerPATCH 429/529 pinctrl: rockchip: fix reading pull type on rk3568
In reply to Greg Kroah-HartmanFrom: Jonas Karlman <[email protected]>
commit 31b62a98de42cf65d76e4dcfb571af067d27d83a upstream.
When reading pinconf-pins from debugfs it fails to get the configured pull type on RK3568, "unsupported pinctrl type" error messages is also reported.
Fix this by adding support for RK3568 in rockchip_get_pull, including a reverse of the pull-up value swap applied in rockchip_set_pull so that pull-up is correctly reported in pinconf-pins.
Also update the workaround comment to reflect affected pins, GPIO0_D3-D6.
--- drivers/pinctrl/pinctrl-rockchip.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
drivers/pinctrl/pinctrl-rockchip.c +10 -1
@@ -2045,9 +2045,18 @@ static int rockchip_get_pull(struct rockcase RK3308 :case RK3368 :case RK3399 : +case RK3568 : pull_type = bank->pull_type[pin_num /8 ]; data >>= bit; data &= (1 <<RK3188_PULL_BITS_PER_PIN ) -1 ; +/* +* In the TRM, pull-up being 1 for everything except the GPIO0_D3-D6, +* where that pull up value becomes 3. +*/ +if (ctrl->type ==RK3568 && bank->bank_num ==0 && pin_num >=27 && pin_num <=30 ) { +if (data ==3 ) + data =1 ; + }return rockchip_pull_list[pull_type][data];default :
@@ -2101,7 +2110,7 @@ static int rockchip_set_pull(struct rock } }/* -* In the TRM, pull-up being 1 for everything except the GPIO0_D0-D6, +* In the TRM, pull-up being 1 for everything except the GPIO0_D3-D6, * where that pull up value becomes 3. */ if (ctrl->type ==RK3568 && bank->bank_num ==0 && pin_num >=27 && pin_num <=30 ) {
Greg Kroah-Hartman
maintainerPATCH 430/529 kbuild: Port silent mode detection to future gnu make.
In reply to Greg Kroah-HartmanFrom: Dmitry Goncharov <[email protected]>
commit 4bf73588165ba7d32131a043775557a54b6e1db5 upstream.
Port silent mode detection to the future (post make-4.4) versions of gnu make.
Makefile contains the following piece of make code to detect if option -s is specified on the command line.
ifneq ($(findstring s,$(filter-out --%,$(MAKEFLAGS))),)
This code is executed by make at parse time and assumes that MAKEFLAGS does not contain command line variable definitions.
Currently if the user defines a=s on the command line, then at build only time MAKEFLAGS contains " -- a=s".
However, starting with commit dc2d963989b96161472b2cd38cef5d1f4851ea34 MAKEFLAGS contains command line definitions at both parse time and build time.
This '-s' detection code then confuses a command line variable definition which contains letter 's' with option -s.
$ # old make $ make net/wireless/ocb.o a=s CALL scripts/checksyscalls.sh DESCEND objtool $ # this a new make which defines makeflags at parse time $ ~/src/gmake/make/l64/make net/wireless/ocb.o a=s $
We can see here that the letter 's' from 'a=s' was confused with -s.
This patch checks for presence of -s using a method recommended by the make manual here
https://www.gnu.org/software/make/manual/make.html#Testing-Flags.
--- Makefile | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
Makefile +9 -2
@@ -93,9 +93,16 @@ endif # If the user is running make -s (silent mode), suppress echoing of # commands +# make-4.0 (and later) keep single letter options in the 1st word of MAKEFLAGS. -ifneq ($(findstring s,$(filter-out --%,$(MAKEFLAGS))),) - quiet=silent_ +ifeq ($(filter 3.%,$(MAKE_VERSION)),) +silence:=$(findstring s,$(firstword -$(MAKEFLAGS))) +else +silence:=$(findstring s,$(filter-out --%,$(MAKEFLAGS))) +endif + +ifeq ($(silence),s) +quiet=silent_ endif export quiet Q KBUILD_VERBOSE
Greg Kroah-Hartman
maintainerPATCH 431/529 net/sched: Retire tcindex classifier
In reply to Greg Kroah-HartmanFrom: Jamal Hadi Salim <[email protected]>
commit 8c710f75256bb3cf05ac7b1672c82b92c43f3d28 upstream.
The tcindex classifier has served us well for about a quarter of a century but has not been getting much TLC due to lack of known users. Most recently it has become easy prey to syzkaller. For this reason, we are retiring it.
--- net/sched/Kconfig | 11 net/sched/Makefile | 1 net/sched/cls_tcindex.c | 756 ------------------------------------------------ 3 files changed, 768 deletions(-) delete mode 100644 net/sched/cls_tcindex.c delete mode 100644 tools/testing/selftests/tc-testing/tc-tests/filters/tcindex.json
net/sched/Kconfig +0 -11
@@ -503,17 +503,6 @@ config NET_CLS_BASIC To compile this code as a module, choose M here: the module will be called cls_basic. -config NET_CLS_TCINDEX - tristate "Traffic-Control Index (TCINDEX)" - select NET_CLS - help - Say Y here if you want to be able to classify packets based on - traffic control indices. You will want this feature if you want - to implement Differentiated Services together with DSMARK. - - To compile this code as a module, choose M here: the - module will be called cls_tcindex. - config NET_CLS_ROUTE4 tristate "Routing decision (ROUTE)" depends on INET
net/sched/Makefile +0 -1
@@ -69,7 +69,6 @@ obj-$(CONFIG_NET_CLS_U32) += cls_u32.o obj-$(CONFIG_NET_CLS_ROUTE4) += cls_route.o obj-$(CONFIG_NET_CLS_FW) += cls_fw.o obj-$(CONFIG_NET_CLS_RSVP) += cls_rsvp.o -obj-$(CONFIG_NET_CLS_TCINDEX) += cls_tcindex.o obj-$(CONFIG_NET_CLS_RSVP6) += cls_rsvp6.o obj-$(CONFIG_NET_CLS_BASIC) += cls_basic.o obj-$(CONFIG_NET_CLS_FLOW) += cls_flow.o
net/sched/cls_tcindex.c deleted +0 -756
756 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 432/529 fs/jfs: fix shift exponent db_agl2size negative
In reply to Greg Kroah-HartmanFrom: Liu Shixin via Jfs-discussion <[email protected]>
[ Upstream commit fad376fce0af58deebc5075b8539dc05bf639af3 ]
As a shift exponent, db_agl2size can not be less than 0. Add the missing check to fix the shift-out-of-bounds bug reported by syzkaller:
UBSAN: shift-out-of-bounds in fs/jfs/jfs_dmap.c:2227:15 shift exponent -744642816 is negative
--- fs/jfs/jfs_dmap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/jfs/jfs_dmap.c +2 -1
@@ -193,7 +193,8 @@ int dbMount(struct inode *ipbmap) bmp->db_agwidth =le32_to_cpu (dbmp_le->dn_agwidth); bmp->db_agstart =le32_to_cpu (dbmp_le->dn_agstart); bmp->db_agl2size =le32_to_cpu (dbmp_le->dn_agl2size); -if (bmp->db_agl2size >L2MAXL2SIZE -L2MAXAG ) { +if (bmp->db_agl2size >L2MAXL2SIZE -L2MAXAG || + bmp->db_agl2size <0 ) { err = -EINVAL ; goto err_release_metapage; }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 433/529 objtool: Fix memory leak in create_static_call_sections()
In reply to Greg Kroah-HartmanFrom: Miaoqian Lin <[email protected]>
[ Upstream commit 3da73f102309fe29150e5c35acd20dd82063ff67 ]
strdup() allocates memory for key_name. We need to release the memory in the following error paths. Add free() to avoid memory leak.
--- tools/objtool/check.c | 2 ++ 1 file changed, 2 insertions(+)
tools/objtool/check.c +2 -0
@@ -572,6 +572,7 @@ static int create_static_call_sections(struct objtool_file *file)if (strncmp (key_name,STATIC_CALL_TRAMP_PREFIX_STR ,STATIC_CALL_TRAMP_PREFIX_LEN )) {WARN ("static_call: trampoline name malformed: %s" , key_name); +free (key_name);return -1 ; } tmp = key_name +STATIC_CALL_TRAMP_PREFIX_LEN -STATIC_CALL_KEY_PREFIX_LEN ;
@@ -581,6 +582,7 @@ static int create_static_call_sections(struct objtool_file *file)if (!key_sym) {if (!module) {WARN ("static_call: can't find static_call_key symbol: %s" , tmp); +free (key_name);return -1 ; }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 434/529 pwm: sifive: Reduce time the controller lock is held
In reply to Greg Kroah-HartmanFrom: Uwe Kleine-König <[email protected]>
[ Upstream commit 0f02f491b786143f08eb19840f1cf4f12aec6dee ]
The lock is only to serialize access and update to user_count and approx_period between different PWMs served by the same pwm_chip. So the lock needs only to be taken during the check if the (chip global) period can and/or needs to be changed.
Stable-dep-of: 334c7b13d383 ("pwm: sifive: Always let the first pwm_apply_state succeed")
--- drivers/pwm/pwm-sifive.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/pwm/pwm-sifive.c +5 -3
@@ -41,7 +41,7 @@struct pwm_sifive_ddata {struct pwm_chip chip; -struct mutex lock;/* lock to protect user_count */ +struct mutex lock;/* lock to protect user_count and approx_period */ struct notifier_block notifier;struct clk *clk;void __iomem *regs;
@@ -76,6 +76,7 @@ static void pwm_sifive_free(struct pwm_chip *chip, struct pwm_device *pwm)mutex_unlock (&ddata->lock); } +/* Called holding ddata->lock */ static void pwm_sifive_update_clock (struct pwm_sifive_ddata *ddata,unsigned long rate) {
@@ -163,7 +164,6 @@ static int pwm_sifive_apply(struct pwm_chip *chip, struct pwm_device *pwm,return ret; } -mutex_lock (&ddata->lock); cur_state = pwm->state; enabled = cur_state.enabled;
@@ -182,14 +182,17 @@ static int pwm_sifive_apply(struct pwm_chip *chip, struct pwm_device *pwm,/* The hardware cannot generate a 100% duty cycle */ frac =min (frac, (1U <<PWM_SIFIVE_CMPWIDTH ) -1 ); +mutex_lock (&ddata->lock);if (state->period != ddata->approx_period) {if (ddata->user_count !=1 ) { +mutex_unlock (&ddata->lock); ret = -EBUSY ; goto exit; } ddata->approx_period = state->period;pwm_sifive_update_clock (ddata,clk_get_rate (ddata->clk)); } +mutex_unlock (&ddata->lock);writel (frac, ddata->regs +PWM_SIFIVE_PWMCMP (pwm->hwpwm));
@@ -198,7 +201,6 @@ static int pwm_sifive_apply(struct pwm_chip *chip, struct pwm_device *pwm, exit:clk_disable (ddata->clk); -mutex_unlock (&ddata->lock);return ret; }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 435/529 pwm: sifive: Always let the first pwm_apply_state succeed
In reply to Greg Kroah-HartmanFrom: Emil Renner Berthing <[email protected]>
[ Upstream commit 334c7b13d38321e47d1a51dba0bef9f4c403ec75 ]
Commit 2cfe9bbec56ea579135cdd92409fff371841904f added support for the RGB and green PWM controlled LEDs on the HiFive Unmatched board managed by the leds-pwm-multicolor and leds-pwm drivers respectively. All three colours of the RGB LED and the green LED run from different lines of the same PWM, but with the same period so this works fine when the LED drivers are loaded one after the other.
Unfortunately it does expose a race in the PWM driver when both LED drivers are loaded at roughly the same time. Here is an example:
| Thread A | Thread B | | led_pwm_mc_probe | led_pwm_probe | | devm_fwnode_pwm_get | | | pwm_sifive_request | | | ddata->user_count++ | | | | devm_fwnode_pwm_get | | | pwm_sifive_request | | | ddata->user_count++ | | ... | ... | | pwm_state_apply | pwm_state_apply | | pwm_sifive_apply | pwm_sifive_apply |
Now both calls to pwm_sifive_apply will see that ddata->approx_period, initially 0, is different from the requested period and the clock needs to be updated. But since ddata->user_count >= 2 both calls will fail with -EBUSY, which will then cause both LED drivers to fail to probe.
Fix it by letting the first call to pwm_sifive_apply update the clock even when ddata->user_count != 1.
--- drivers/pwm/pwm-sifive.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/pwm/pwm-sifive.c +7 -1
@@ -184,7 +184,13 @@ static int pwm_sifive_apply(struct pwm_chip *chip, struct pwm_device *pwm,mutex_lock (&ddata->lock);if (state->period != ddata->approx_period) { -if (ddata->user_count !=1 ) { +/* +* Don't let a 2nd user change the period underneath the 1st user. +* However if ddate->approx_period == 0 this is the first time we set +* any period, so let whoever gets here first set the period so other +* users who agree on the period won't fail. +*/ +if (ddata->user_count !=1 && ddata->approx_period) {mutex_unlock (&ddata->lock); ret = -EBUSY ; goto exit;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 436/529 pwm: stm32-lp: fix the check on arr and cmp registers update
In reply to Greg Kroah-HartmanFrom: Fabrice Gasnier <[email protected]>
[ Upstream commit 3066bc2d58be31275afb51a589668f265e419c37 ]
The ARR (auto reload register) and CMP (compare) registers are successively written. The status bits to check the update of these registers are polled together with regmap_read_poll_timeout(). The condition to end the loop may become true, even if one of the register isn't correctly updated.
So ensure both status bits are set before clearing them.
--- drivers/pwm/pwm-stm32-lp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pwm/pwm-stm32-lp.c +1 -1
@@ -127,7 +127,7 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,/* ensure CMP & ARR registers are properly written */ ret =regmap_read_poll_timeout (priv->regmap,STM32_LPTIM_ISR , val, - (val &STM32_LPTIM_CMPOK_ARROK ), + (val &STM32_LPTIM_CMPOK_ARROK ) ==STM32_LPTIM_CMPOK_ARROK ,100 ,1000 );if (ret) {dev_err (priv->chip.dev,"ARR/CMP registers write issue\n" );
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 437/529 f2fs: use memcpy_{to,from}_page() where possible
In reply to Greg Kroah-HartmanFrom: Eric Biggers <[email protected]>
[ Upstream commit b87846bd61c7c09560617da416208a5454530d57 ]
This is simpler, and as a side effect it replaces several uses of kmap_atomic() with its recommended replacement kmap_local_page().
Stable-dep-of: b1b9896718bc ("fs: f2fs: initialize fsdata in pagecache_write()")
--- fs/f2fs/inline.c | 15 ++++----------- fs/f2fs/super.c | 11 ++--------- fs/f2fs/verity.c | 10 ++-------- 3 files changed, 8 insertions(+), 28 deletions(-)
fs/f2fs/inline.c +4 -11
@@ -64,7 +64,6 @@ bool f2fs_may_inline_dentry(struct inode *inode)void f2fs_do_read_inline_data (struct page *page,struct page *ipage) {struct inode *inode = page->mapping->host; -void *src_addr, *dst_addr;if (PageUptodate (page))return ;
@@ -74,11 +73,8 @@ void f2fs_do_read_inline_data(struct page *page, struct page *ipage)zero_user_segment (page,MAX_INLINE_DATA (inode),PAGE_SIZE );/* Copy the whole inline data block */ - src_addr =inline_data_addr (inode, ipage); - dst_addr =kmap_atomic (page); -memcpy (dst_addr, src_addr,MAX_INLINE_DATA (inode)); -flush_dcache_page (page); -kunmap_atomic (dst_addr); +memcpy_to_page (page,0 ,inline_data_addr (inode, ipage), +MAX_INLINE_DATA (inode));if (!PageUptodate (page))SetPageUptodate (page); }
@@ -245,7 +241,6 @@ int f2fs_convert_inline_inode(struct inode *inode)int f2fs_write_inline_data (struct inode *inode,struct page *page) { -void *src_addr, *dst_addr;struct dnode_of_data dn;int err;
@@ -262,10 +257,8 @@ int f2fs_write_inline_data(struct inode *inode, struct page *page)f2fs_bug_on (F2FS_I_SB (inode), page->index);f2fs_wait_on_page_writeback (dn.inode_page,NODE , true, true); - src_addr =kmap_atomic (page); - dst_addr =inline_data_addr (inode, dn.inode_page); -memcpy (dst_addr, src_addr,MAX_INLINE_DATA (inode)); -kunmap_atomic (src_addr); +memcpy_from_page (inline_data_addr (inode, dn.inode_page), + page,0 ,MAX_INLINE_DATA (inode));set_page_dirty (dn.inode_page);f2fs_clear_page_cache_dirty_tag (page);
fs/f2fs/super.c +2 -9
@@ -2034,7 +2034,6 @@ static ssize_t f2fs_quota_read(struct super_block *sb, int type, char *data,size_t toread;loff_t i_size =i_size_read (inode);struct page *page; -char *kaddr;if (off > i_size)return 0 ;
@@ -2068,9 +2067,7 @@ static ssize_t f2fs_quota_read(struct super_block *sb, int type, char *data,return -EIO ; } - kaddr =kmap_atomic (page); -memcpy (data, kaddr + offset, tocopy); -kunmap_atomic (kaddr); +memcpy_from_page (data, page, offset, tocopy);f2fs_put_page (page,1 ); offset =0 ;
@@ -2092,7 +2089,6 @@ static ssize_t f2fs_quota_write(struct super_block *sb, int type,size_t towrite = len;struct page *page;void *fsdata =NULL ; -char *kaddr;int err =0 ;int tocopy;
@@ -2112,10 +2108,7 @@ static ssize_t f2fs_quota_write(struct super_block *sb, int type,break ; } - kaddr =kmap_atomic (page); -memcpy (kaddr + offset, data, tocopy); -kunmap_atomic (kaddr); -flush_dcache_page (page); +memcpy_to_page (page, offset, data, tocopy); a_ops->write_end (NULL , mapping, off, tocopy, tocopy, page, fsdata);
fs/f2fs/verity.c +2 -8
@@ -47,16 +47,13 @@ static int pagecache_read(struct inode *inode, void *buf, size_t count,size_t n =min_t (size_t, count,PAGE_SIZE -offset_in_page (pos));struct page *page; -void *addr; page =read_mapping_page (inode->i_mapping, pos >>PAGE_SHIFT ,NULL );if (IS_ERR (page))return PTR_ERR (page); - addr =kmap_atomic (page); -memcpy (buf, addr +offset_in_page (pos), n); -kunmap_atomic (addr); +memcpy_from_page (buf, page,offset_in_page (pos), n);put_page (page);
@@ -82,7 +79,6 @@ static int pagecache_write(struct inode *inode, const void *buf, size_t count, PAGE_SIZE - offset_in_page(pos));struct page *page;void *fsdata; -void *addr;int res; res = pagecache_write_begin(NULL, inode->i_mapping, pos, n, 0,
@@ -90,9 +86,7 @@ static int pagecache_write(struct inode *inode, const void *buf, size_t count,if (res)return res; - addr =kmap_atomic (page); -memcpy (addr +offset_in_page (pos), buf, n); -kunmap_atomic (addr); +memcpy_to_page (page,offset_in_page (pos), buf, n); res =pagecache_write_end (NULL , inode->i_mapping, pos, n, n, page, fsdata);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 438/529 fs: f2fs: initialize fsdata in pagecache_write()
In reply to Greg Kroah-HartmanFrom: Alexander Potapenko <[email protected]>
[ Upstream commit b1b9896718bc1a212dc288ad66a5fa2fef11353d ]
When aops->write_begin() does not initialize fsdata, KMSAN may report an error passing the latter to aops->write_end().
Fix this by unconditionally initializing fsdata.
--- fs/f2fs/verity.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/f2fs/verity.c +1 -1
@@ -78,7 +78,7 @@ static int pagecache_write(struct inode *inode, const void *buf, size_t count,size_t n =min_t (size_t, count,PAGE_SIZE -offset_in_page (pos));struct page *page; -void *fsdata; +void *fsdata =NULL ;int res; res = pagecache_write_begin(NULL, inode->i_mapping, pos, n, 0,
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 439/529 um: vector: Fix memory leak in vector_config
In reply to Greg Kroah-HartmanFrom: Xiang Yang <[email protected]>
[ Upstream commit 8f88c73afe481f93d40801596927e8c0047b6d96 ]
If the return value of the uml_parse_vector_ifspec function is NULL, we should call kfree(params) to prevent memory leak.
--- arch/um/drivers/vector_kern.c | 1 + 1 file changed, 1 insertion(+)
arch/um/drivers/vector_kern.c +1 -0
@@ -771,6 +771,7 @@ static int vector_config(char *str, char **error_out)if (parsed ==NULL ) { *error_out ="vector_config failed to parse parameters" ; +kfree (params);return -EINVAL ; }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 440/529 ubi: ensure that VID header offset + VID header size <= alloc, size
In reply to Greg Kroah-HartmanFrom: George Kennedy <[email protected]>
[ Upstream commit 1b42b1a36fc946f0d7088425b90d491b4257ca3e ]
Ensure that the VID header offset + VID header size does not exceed the allocated area to avoid slab OOB.
BUG: KASAN: slab-out-of-bounds in crc32_body lib/crc32.c:111 [inline] BUG: KASAN: slab-out-of-bounds in crc32_le_generic lib/crc32.c:179 [inline] BUG: KASAN: slab-out-of-bounds in crc32_le_base+0x58c/0x626 lib/crc32.c:197 Read of size 4 at addr ffff88802bb36f00 by task syz-executor136/1555 CPU: 2 PID: 1555 Comm: syz-executor136 Tainted: G W 6.0.0-1868 #1 Hardware name: Red Hat KVM, BIOS 1.13.0-2.module+el8.3.0+7860+a7792d29 04/01/2014 Call Trace: <TASK> __dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0x85/0xad lib/dump_stack.c:106 print_address_description mm/kasan/report.c:317 [inline] print_report.cold.13+0xb6/0x6bb mm/kasan/report.c:433 kasan_report+0xa7/0x11b mm/kasan/report.c:495 crc32_body lib/crc32.c:111 [inline] crc32_le_generic lib/crc32.c:179 [inline] crc32_le_base+0x58c/0x626 lib/crc32.c:197 ubi_io_write_vid_hdr+0x1b7/0x472 drivers/mtd/ubi/io.c:1067 create_vtbl+0x4d5/0x9c4 drivers/mtd/ubi/vtbl.c:317 create_empty_lvol drivers/mtd/ubi/vtbl.c:500 [inline] ubi_read_volume_table+0x67b/0x288a drivers/mtd/ubi/vtbl.c:812 ubi_attach+0xf34/0x1603 drivers/mtd/ubi/attach.c:1601 ubi_attach_mtd_dev+0x6f3/0x185e drivers/mtd/ubi/build.c:965 ctrl_cdev_ioctl+0x2db/0x347 drivers/mtd/ubi/cdev.c:1043 vfs_ioctl fs/ioctl.c:51 [inline] __do_sys_ioctl fs/ioctl.c:870 [inline] __se_sys_ioctl fs/ioctl.c:856 [inline] __x64_sys_ioctl+0x193/0x213 fs/ioctl.c:856 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x3e/0x86 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x63/0x0 RIP: 0033:0x7f96d5cf753d
Code:
RSP: 002b:00007fffd72206f8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f96d5cf753d
RDX: 0000000020000080 RSI: 0000000040186f40 RDI: 0000000000000003
RBP: 0000000000400cd0 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000400be0
R13: 00007fffd72207e0 R14: 0000000000000000 R15: 0000000000000000
</TASK> Allocated by task 1555: kasan_save_stack+0x20/0x3d mm/kasan/common.c:38 kasan_set_track mm/kasan/common.c:45 [inline] set_alloc_info mm/kasan/common.c:437 [inline] ____kasan_kmalloc mm/kasan/common.c:516 [inline] __kasan_kmalloc+0x88/0xa3 mm/kasan/common.c:525 kasan_kmalloc include/linux/kasan.h:234 [inline] __kmalloc+0x138/0x257 mm/slub.c:4429 kmalloc include/linux/slab.h:605 [inline] ubi_alloc_vid_buf drivers/mtd/ubi/ubi.h:1093 [inline] create_vtbl+0xcc/0x9c4 drivers/mtd/ubi/vtbl.c:295 create_empty_lvol drivers/mtd/ubi/vtbl.c:500 [inline] ubi_read_volume_table+0x67b/0x288a drivers/mtd/ubi/vtbl.c:812 ubi_attach+0xf34/0x1603 drivers/mtd/ubi/attach.c:1601 ubi_attach_mtd_dev+0x6f3/0x185e drivers/mtd/ubi/build.c:965 ctrl_cdev_ioctl+0x2db/0x347 drivers/mtd/ubi/cdev.c:1043 vfs_ioctl fs/ioctl.c:51 [inline] __do_sys_ioctl fs/ioctl.c:870 [inline] __se_sys_ioctl fs/ioctl.c:856 [inline] __x64_sys_ioctl+0x193/0x213 fs/ioctl.c:856 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x3e/0x86 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x63/0x0 The buggy address belongs to the object at ffff88802bb36e00 which belongs to the cache kmalloc-256 of size 256
The buggy address is located 0 bytes to the right of
256-byte region [ffff88802bb36e00, ffff88802bb36f00)
The buggy address belongs to the physical page:
page:00000000ea4d1263 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x2bb36
head:00000000ea4d1263 order:1 compound_mapcount:0 compound_pincount:0
flags: 0xfffffc0010200(slab|head|node=0|zone=1|lastcpupid=0x1fffff)
raw: 000fffffc0010200 ffffea000066c300 dead000000000003 ffff888100042b40
raw: 0000000000000000 0000000000100010 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff88802bb36e00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ffff88802bb36e80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>ffff88802bb36f00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
^
ffff88802bb36f80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff88802bb37000: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================--- drivers/mtd/ubi/build.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/mtd/ubi/build.c +6 -0
@@ -664,6 +664,12 @@ static int io_init(struct ubi_device *ubi, int max_beb_per1024) ubi->ec_hdr_alsize =ALIGN (UBI_EC_HDR_SIZE , ubi->hdrs_min_io_size); ubi->vid_hdr_alsize =ALIGN (UBI_VID_HDR_SIZE , ubi->hdrs_min_io_size); +if (ubi->vid_hdr_offset && ((ubi->vid_hdr_offset +UBI_VID_HDR_SIZE ) > + ubi->vid_hdr_alsize)) { +ubi_err (ubi,"VID header offset %d too large." , ubi->vid_hdr_offset); +return -EINVAL ; + } +dbg_gen ("min_io_size %d" , ubi->min_io_size);dbg_gen ("max_write_size %d" , ubi->max_write_size);dbg_gen ("hdrs_min_io_size %d" , ubi->hdrs_min_io_size);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 441/529 ubifs: Fix build errors as symbol undefined
In reply to Greg Kroah-HartmanFrom: Li Hua <[email protected]>
[ Upstream commit aa6d148e6d6270274e3d5a529b71c54cd329d17f ]
With CONFIG_UBIFS_FS_AUTHENTICATION not set, the compiler can assume that ubifs_node_check_hash() is never true and drops the call to ubifs_bad_hash(). Is CONFIG_CC_OPTIMIZE_FOR_SIZE enabled this optimization does not happen anymore.
So When CONFIG_UBIFS_FS and CONFIG_CC_OPTIMIZE_FOR_SIZE is enabled but CONFIG_UBIFS_FS_AUTHENTICATION is not set, the build errors is as followd:
ERROR: modpost: "ubifs_bad_hash" [fs/ubifs/ubifs.ko] undefined!
Fix it by add no-op ubifs_bad_hash() for the CONFIG_UBIFS_FS_AUTHENTICATION=n case.
--- fs/ubifs/ubifs.h | 5 +++++ 1 file changed, 5 insertions(+)
fs/ubifs/ubifs.h +5 -0
@@ -1594,8 +1594,13 @@ static inline int ubifs_check_hmac(const struct ubifs_info *c,return crypto_memneq (expected, got, c->hmac_desc_len); } +#ifdef CONFIG_UBIFS_FS_AUTHENTICATION void ubifs_bad_hash (const struct ubifs_info *c,const void *node,const u8 *hash,int lnum,int offs); +#else +static inline void ubifs_bad_hash (const struct ubifs_info *c,const void *node, +const u8 *hash,int lnum,int offs) {}; +#endif int __ubifs_node_check_hash (const struct ubifs_info *c,const void *buf,const u8 *expected);
Signature · 1 line
2.39.2