4.4.244-rc1 review
Subsystems (2)
Greg Kroah-Hartman
maintainercover 4.4.244-rc1 review
This is the start of the stable review cycle for the 4.4.244 release. There are 64 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 19 Nov 2020 12:20:51 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.4.244-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-4.4.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 4.4.244-rc1
Boris Protopopov <[email protected]>
Convert trailing spaces and periods in path components
Eric Biggers <[email protected]>
ext4: fix leaking sysfs kobject after failed mount
Matteo Croce <[email protected]>
reboot: fix overflow parsing reboot cpu number
Matteo Croce <[email protected]>
Revert "kernel/reboot.c: convert simple_strtoul to kstrtoint"
Jiri Olsa <[email protected]>
perf/core: Fix race in the perf_mmap_close() function
Juergen Gross <[email protected]>
xen/events: block rogue events for some time
Juergen Gross <[email protected]>
xen/events: defer eoi in case of excessive number of events
Juergen Gross <[email protected]>
xen/events: use a common cpu hotplug hook for event channels
Juergen Gross <[email protected]>
xen/events: switch user event channels to lateeoi model
Juergen Gross <[email protected]>
xen/pciback: use lateeoi irq binding
Juergen Gross <[email protected]>
xen/scsiback: use lateeoi irq binding
Juergen Gross <[email protected]>
xen/netback: use lateeoi irq binding
Juergen Gross <[email protected]>
xen/blkback: use lateeoi irq binding
Juergen Gross <[email protected]>
xen/events: add a new "late EOI" evtchn framework
Juergen Gross <[email protected]>
xen/events: fix race in evtchn_fifo_unmask()
Juergen Gross <[email protected]>
xen/events: add a proper barrier to 2-level uevent unmasking
Juergen Gross <[email protected]>
xen/events: avoid removing an event channel while handling it
Anand K Mistry <[email protected]>
x86/speculation: Allow IBPB to be conditionally enabled on CPUs with always-on STIBP
George Spelvin <[email protected]>
random32: make prandom_u32() output unpredictable
Mao Wenan <[email protected]>
net: Update window_clamp if SOCK_RCVBUF is set
Martin Schiller <[email protected]>
net/x25: Fix null-ptr-deref in x25_connect
Ursula Braun <[email protected]>
net/af_iucv: fix null pointer dereference on shutdown
Oliver Herms <[email protected]>
IPv6: Set SIT tunnel hard_header_len to zero
Stefano Stabellini <[email protected]>
swiotlb: fix "x86: Don't panic if can not alloc buffer for swiotlb"
Coiby Xu <[email protected]>
pinctrl: amd: fix incorrect way to disable debounce filter
Coiby Xu <[email protected]>
pinctrl: amd: use higher precision for 512 RtcClk
Thomas Zimmermann <[email protected]>
drm/gma500: Fix out-of-bounds access to struct drm_device.vblank[]
Al Viro <[email protected]>
don't dump the threads that had been already exiting when zapped.
Wengang Wang <[email protected]>
ocfs2: initialize ip_next_orphan
Alexander Usyskin <[email protected]>
mei: protect mei_cl_mtu from null dereference
Chris Brandt <[email protected]>
usb: cdc-acm: Add DISABLE_ECHO for Renesas USB Download mode
Joseph Qi <[email protected]>
ext4: unlock xattr_sem properly in ext4_inline_data_truncate()
Kaixu Xia <[email protected]>
ext4: correctly report "not supported" for {usr,grp}jquota when !CONFIG_QUOTA
Peter Zijlstra <[email protected]>
perf: Fix get_recursion_context()
Wang Hai <[email protected]>
cosa: Add missing kfree in error path of cosa_write
Evan Nimmo <[email protected]>
of/address: Fix of_node memory leak in of_dma_is_coherent
Christoph Hellwig <[email protected]>
xfs: fix a missing unlock on error in xfs_fs_map_blocks
Suravee Suthikulpanit <[email protected]>
iommu/amd: Increase interrupt remapping table limit to 512 entries
Ye Bin <[email protected]>
cfg80211: regulatory: Fix inconsistent format argument
Johannes Berg <[email protected]>
mac80211: always wind down STA state
Johannes Berg <[email protected]>
mac80211: fix use of skb payload instead of header
Evan Quan <[email protected]>
drm/amdgpu: perform srbm soft reset always on SDMA resume
Bob Peterson <[email protected]>
gfs2: check for live vs. read-only file system in gfs2_fitrim
Bob Peterson <[email protected]>
gfs2: Free rd_bits later in gfs2_clear_rgrpd to fix use-after-free
Evgeny Novikov <[email protected]>
usb: gadget: goku_udc: fix potential crashes in probe
Masashi Honma <[email protected]>
ath9k_htc: Use appropriate rs_datalen type
Mark Gray <[email protected]>
geneve: add transport ports in route lookup for geneve
Martyna Szapar <[email protected]>
i40e: Fix of memory leak and integer truncation in i40e_virtchnl.c
Grzegorz Siwik <[email protected]>
i40e: Wrong truncation from u16 to u8
Will Deacon <[email protected]>
pinctrl: devicetree: Avoid taking direct reference to device name string
Filipe Manana <[email protected]>
Btrfs: fix missing error return if writeback for extent buffer never started
Stephane Grosjean <[email protected]>
can: peak_usb: peak_usb_get_ts_time(): fix timestamp wrapping
Dan Carpenter <[email protected]>
can: peak_usb: add range checking in decode operations
Oleksij Rempel <[email protected]>
can: can_create_echo_skb(): fix echo skb generation: always use skb_clone()
Oliver Hartkopp <[email protected]>
can: dev: __can_get_echo_skb(): fix real payload length return value for RTR frames
Vincent Mailhol <[email protected]>
can: dev: can_get_echo_skb(): prevent call to kfree_skb() in hard IRQ context
Dan Carpenter <[email protected]>
ALSA: hda: prevent undefined shift in snd_hdac_ext_bus_get_link()
Jiri Olsa <[email protected]>
perf tools: Add missing swap for ino_generation
zhuoliang zhang <[email protected]>
net: xfrm: fix a race condition during allocing spi
Johannes Thumshirn <[email protected]>
btrfs: reschedule when cloning lots of extents
Zeng Tao <[email protected]>
time: Prevent undefined behaviour in timespec64_to_ns()
Shijie Luo <[email protected]>
mm: mempolicy: fix potential pte_unmap_unlock pte error
Alexander Aring <[email protected]>
gfs2: Wake up when sd_glock_disposal becomes zero
Steven Rostedt (VMware) <[email protected]>
ring-buffer: Fix recursion protection transitions between interrupt context
-------------
Diffstat:
Documentation/kernel-parameters.txt | 8 + Makefile | 4 +- arch/x86/kernel/cpu/bugs.c | 52 ++- drivers/block/xen-blkback/blkback.c | 22 +- drivers/block/xen-blkback/xenbus.c | 5 +- drivers/char/random.c | 2 - drivers/gpu/drm/amd/amdgpu/cik_sdma.c | 27 +- drivers/gpu/drm/gma500/psb_irq.c | 34 +- drivers/iommu/amd_iommu_types.h | 6 +- drivers/misc/mei/client.h | 4 +- drivers/net/can/dev.c | 14 +- drivers/net/can/usb/peak_usb/pcan_usb_core.c | 51 ++- drivers/net/can/usb/peak_usb/pcan_usb_fd.c | 48 ++- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 4 +- drivers/net/geneve.c | 36 +- drivers/net/wan/cosa.c | 1 + drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 2 +- drivers/net/xen-netback/common.h | 39 ++ drivers/net/xen-netback/interface.c | 59 ++- drivers/net/xen-netback/netback.c | 17 +- drivers/of/address.c | 4 +- drivers/pinctrl/devicetree.c | 26 +- drivers/pinctrl/pinctrl-amd.c | 6 +- drivers/usb/class/cdc-acm.c | 9 + drivers/usb/gadget/udc/goku_udc.c | 2 +- drivers/xen/events/events_2l.c | 9 +- drivers/xen/events/events_base.c | 444 ++++++++++++++++++-- drivers/xen/events/events_fifo.c | 102 ++--- drivers/xen/events/events_internal.h | 20 +- drivers/xen/evtchn.c | 7 +- drivers/xen/xen-pciback/pci_stub.c | 14 +- drivers/xen/xen-pciback/pciback.h | 12 +- drivers/xen/xen-pciback/pciback_ops.c | 48 ++- drivers/xen/xen-pciback/xenbus.c | 2 +- drivers/xen/xen-scsiback.c | 23 +- fs/btrfs/extent_io.c | 4 + fs/btrfs/ioctl.c | 2 + fs/cifs/cifs_unicode.c | 8 +- fs/ext4/inline.c | 1 + fs/ext4/super.c | 5 +- fs/gfs2/glock.c | 3 +- fs/gfs2/rgrp.c | 5 +- fs/ocfs2/super.c | 1 + fs/xfs/xfs_pnfs.c | 2 +- include/linux/can/skb.h | 20 +- include/linux/prandom.h | 36 +- include/linux/time64.h | 4 + include/xen/events.h | 29 +- kernel/events/core.c | 7 +- kernel/events/internal.h | 2 +- kernel/exit.c | 5 +- kernel/reboot.c | 28 +- kernel/time/timer.c | 7 - kernel/trace/ring_buffer.c | 54 ++- lib/random32.c | 463 +++++++++++++-------- lib/swiotlb.c | 6 +- mm/mempolicy.c | 6 +- net/ipv4/syncookies.c | 9 +- net/ipv6/sit.c | 2 - net/ipv6/syncookies.c | 10 +- net/iucv/af_iucv.c | 3 +- net/mac80211/sta_info.c | 18 + net/mac80211/tx.c | 35 +- net/wireless/reg.c | 2 +- net/x25/af_x25.c | 2 +- net/xfrm/xfrm_state.c | 8 +- sound/hda/ext/hdac_ext_controller.c | 2 + tools/perf/util/session.c | 1 + 68 files changed, 1431 insertions(+), 522 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/64 ring-buffer: Fix recursion protection transitions between interrupt context
From: Steven Rostedt (VMware) <[email protected]>
[ Upstream commit b02414c8f045ab3b9afc816c3735bc98c5c3d262 ]
The recursion protection of the ring buffer depends on preempt_count() to be correct. But it is possible that the ring buffer gets called after an interrupt comes in but before it updates the preempt_count(). This will trigger a false positive in the recursion code.
Use the same trick from the ftrace function callback recursion code which uses a "transition" bit that gets set, to allow for a single recursion for to handle transitions between contexts.
--- kernel/trace/ring_buffer.c | 54 +++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 10 deletions(-)
kernel/trace/ring_buffer.c +44 -10
@@ -416,14 +416,16 @@ struct rb_event_info {/* * Used for which event context the event is in. -* NMI = 0 -* IRQ = 1 -* SOFTIRQ = 2 -* NORMAL = 3 +* TRANSITION = 0 +* NMI = 1 +* IRQ = 2 +* SOFTIRQ = 3 +* NORMAL = 4 * * See trace_recursive_lock() comment below for more details. */ enum { +RB_CTX_TRANSITION ,RB_CTX_NMI ,RB_CTX_IRQ ,RB_CTX_SOFTIRQ ,
@@ -2585,10 +2587,10 @@ rb_wakeups(struct ring_buffer *buffer, struct ring_buffer_per_cpu *cpu_buffer)* a bit of overhead in something as critical as function tracing, * we use a bitmask trick. * -* bit 0 = NMI context -* bit 1 = IRQ context -* bit 2 = SoftIRQ context -* bit 3 = normal context. +* bit 1 = NMI context +* bit 2 = IRQ context +* bit 3 = SoftIRQ context +* bit 4 = normal context. * * This works because this is the order of contexts that can * preempt other contexts. A SoftIRQ never preempts an IRQ
@@ -2611,6 +2613,30 @@ rb_wakeups(struct ring_buffer *buffer, struct ring_buffer_per_cpu *cpu_buffer)* The least significant bit can be cleared this way, and it * just so happens that it is the same bit corresponding to * the current context. +* +* Now the TRANSITION bit breaks the above slightly. The TRANSITION bit +* is set when a recursion is detected at the current context, and if +* the TRANSITION bit is already set, it will fail the recursion. +* This is needed because there's a lag between the changing of +* interrupt context and updating the preempt count. In this case, +* a false positive will be found. To handle this, one extra recursion +* is allowed, and this is done by the TRANSITION bit. If the TRANSITION +* bit is already set, then it is considered a recursion and the function +* ends. Otherwise, the TRANSITION bit is set, and that bit is returned. +* +* On the trace_recursive_unlock(), the TRANSITION bit will be the first +* to be cleared. Even if it wasn't the context that set it. That is, +* if an interrupt comes in while NORMAL bit is set and the ring buffer +* is called before preempt_count() is updated, since the check will +* be on the NORMAL bit, the TRANSITION bit will then be set. If an +* NMI then comes in, it will set the NMI bit, but when the NMI code +* does the trace_recursive_unlock() it will clear the TRANSTION bit +* and leave the NMI bit set. But this is fine, because the interrupt +* code that set the TRANSITION bit will then clear the NMI bit when it +* calls trace_recursive_unlock(). If another NMI comes in, it will +* set the TRANSITION bit and continue. +* +* Note: The TRANSITION bit only handles a single transition between context. */ static __always_inline int
@@ -2629,8 +2655,16 @@ trace_recursive_lock(struct ring_buffer_per_cpu *cpu_buffer) }else bit =RB_CTX_NORMAL ; -if (unlikely (val & (1 << bit))) -return 1 ; +if (unlikely (val & (1 << bit))) { +/* +* It is possible that this was called by transitioning +* between interrupt context, and preempt_count() has not +* been updated yet. In this case, use the TRANSITION bit. +*/ + bit =RB_CTX_TRANSITION ; +if (val & (1 << bit)) +return 1 ; + } val |= (1 << bit); cpu_buffer->current_context = val;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 2/64 gfs2: Wake up when sd_glock_disposal becomes zero
In reply to Greg Kroah-HartmanFrom: Alexander Aring <[email protected]>
[ Upstream commit da7d554f7c62d0c17c1ac3cc2586473c2d99f0bd ]
Commit fc0e38dae645 ("GFS2: Fix glock deallocation race") fixed a sd_glock_disposal accounting bug by adding a missing atomic_dec statement, but it failed to wake up sd_glock_wait when that decrement causes sd_glock_disposal to reach zero. As a consequence, gfs2_gl_hash_clear can now run into a 10-minute timeout instead of being woken up. Add the missing wakeup.
--- fs/gfs2/glock.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/gfs2/glock.c +2 -1
@@ -751,7 +751,8 @@ again: }kfree (gl->gl_lksb.sb_lvbptr);kmem_cache_free (cachep, gl); -atomic_dec (&sdp->sd_glock_disposal); +if (atomic_dec_and_test (&sdp->sd_glock_disposal)) +wake_up (&sdp->sd_glock_wait); *glp = tmp;return ret;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 3/64 mm: mempolicy: fix potential pte_unmap_unlock pte error
In reply to Greg Kroah-HartmanFrom: Shijie Luo <[email protected]>
[ Upstream commit 3f08842098e842c51e3b97d0dcdebf810b32558e ]
When flags in queue_pages_pte_range don't have MPOL_MF_MOVE or MPOL_MF_MOVE_ALL bits, code breaks and passing origin pte - 1 to pte_unmap_unlock seems like not a good idea.
queue_pages_pte_range can run in MPOL_MF_MOVE_ALL mode which doesn't migrate misplaced pages but returns with EIO when encountering such a page. Since commit a7f40cfe3b7a ("mm: mempolicy: make mbind() return -EIO when MPOL_MF_STRICT is specified") and early break on the first pte in the range results in pte_unmap_unlock on an underflow pte. This can lead to lockups later on when somebody tries to lock the pte resp. page_table_lock again..
--- mm/mempolicy.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
mm/mempolicy.c +3 -3
@@ -490,14 +490,14 @@ static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,struct queue_pages *qp = walk->private;unsigned long flags = qp->flags;int nid; -pte_t *pte; +pte_t *pte, *mapped_pte;spinlock_t *ptl;split_huge_page_pmd (vma, addr, pmd);if (pmd_trans_unstable (pmd))return 0 ; - pte =pte_offset_map_lock (walk->mm, pmd, addr, &ptl); + mapped_pte = pte =pte_offset_map_lock (walk->mm, pmd, addr, &ptl);for (; addr != end; pte++, addr +=PAGE_SIZE ) {if (!pte_present (*pte))continue ;
@@ -521,7 +521,7 @@ static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr, }else break ; } -pte_unmap_unlock (pte -1 , ptl); +pte_unmap_unlock (mapped_pte, ptl);cond_resched ();return addr != end ? -EIO :0 ; }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 4/64 time: Prevent undefined behaviour in timespec64_to_ns()
In reply to Greg Kroah-HartmanFrom: Zeng Tao <[email protected]>
[ Upstream commit cb47755725da7b90fecbb2aa82ac3b24a7adb89b ]
UBSAN reports:
Undefined behaviour in ./include/linux/time64.h:127:27 signed integer overflow:
17179869187 * 1000000000 cannot be represented in type 'long long int'
Call Trace: timespec64_to_ns include/linux/time64.h:127 [inline] set_cpu_itimer+0x65c/0x880 kernel/time/itimer.c:180 do_setitimer+0x8e/0x740 kernel/time/itimer.c:245 __x64_sys_setitimer+0x14c/0x2c0 kernel/time/itimer.c:336 do_syscall_64+0xa1/0x540 arch/x86/entry/common.c:295
Commit bd40a175769d ("y2038: itimer: change implementation to timespec64") replaced the original conversion which handled time clamping correctly with timespec64_to_ns() which has no overflow protection.
Fix it in timespec64_to_ns() as this is not necessarily limited to the usage in itimers.
[ tglx: Added comment and adjusted the fixes tag ]
--- include/linux/time64.h | 4 ++++ 1 file changed, 4 insertions(+)
include/linux/time64.h +4 -0
@@ -197,6 +197,10 @@ static inline bool timespec64_valid_strict(const struct timespec64 *ts)*/ static inline s64 timespec64_to_ns (const struct timespec64 *ts) { +/* Prevent multiplication overflow */ +if ((unsigned long long )ts->tv_sec >=KTIME_SEC_MAX ) +return KTIME_MAX ; +return ((s64 ) ts->tv_sec *NSEC_PER_SEC ) + ts->tv_nsec; }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 5/64 btrfs: reschedule when cloning lots of extents
In reply to Greg Kroah-HartmanFrom: Johannes Thumshirn <[email protected]>
[ Upstream commit 6b613cc97f0ace77f92f7bc112b8f6ad3f52baf8 ]
We have several occurrences of a soft lockup from fstest's generic/175 testcase, which look more or less like this one:
watchdog: BUG: soft lockup - CPU#0 stuck for 22s! [xfs_io:10030] Kernel panic - not syncing: softlockup: hung tasks CPU: 0 PID: 10030 Comm: xfs_io Tainted: G L 5.9.0-rc5+ #768 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.13.0-0-gf21b5a4-rebuilt.opensuse.org 04/01/2014 Call Trace: <IRQ> dump_stack+0x77/0xa0 panic+0xfa/0x2cb watchdog_timer_fn.cold+0x85/0xa5 ? lockup_detector_update_enable+0x50/0x50 __hrtimer_run_queues+0x99/0x4c0 ? recalibrate_cpu_khz+0x10/0x10 hrtimer_run_queues+0x9f/0xb0 update_process_times+0x28/0x80 tick_handle_periodic+0x1b/0x60 __sysvec_apic_timer_interrupt+0x76/0x210 asm_call_on_stack+0x12/0x20 </IRQ> sysvec_apic_timer_interrupt+0x7f/0x90 asm_sysvec_apic_timer_interrupt+0x12/0x20 RIP: 0010:btrfs_tree_unlock+0x91/0x1a0 [btrfs] RSP: 0018:ffffc90007123a58 EFLAGS: 00000282 RAX: ffff8881cea2fbe0 RBX: ffff8881cea2fbe0 RCX: 0000000000000000 RDX: ffff8881d23fd200 RSI: ffffffff82045220 RDI: ffff8881cea2fba0 RBP: 0000000000000001 R08: 0000000000000000 R09: 0000000000000032 R10: 0000160000000000 R11: 0000000000001000 R12: 0000000000001000 R13: ffff8882357fd5b0 R14: ffff88816fa76e70 R15: ffff8881cea2fad0 ? btrfs_tree_unlock+0x15b/0x1a0 [btrfs] btrfs_release_path+0x67/0x80 [btrfs] btrfs_insert_replace_extent+0x177/0x2c0 [btrfs] btrfs_replace_file_extents+0x472/0x7c0 [btrfs] btrfs_clone+0x9ba/0xbd0 [btrfs] btrfs_clone_files.isra.0+0xeb/0x140 [btrfs] ? file_update_time+0xcd/0x120 btrfs_remap_file_range+0x322/0x3b0 [btrfs] do_clone_file_range+0xb7/0x1e0 vfs_clone_file_range+0x30/0xa0 ioctl_file_clone+0x8a/0xc0 do_vfs_ioctl+0x5b2/0x6f0 __x64_sys_ioctl+0x37/0xa0 do_syscall_64+0x33/0x40 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x7f87977fc247 RSP: 002b:00007ffd51a2f6d8 EFLAGS: 00000206 ORIG_RAX: 0000000000000010 RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f87977fc247 RDX: 00007ffd51a2f710 RSI: 000000004020940d RDI: 0000000000000003 RBP: 0000000000000004 R08: 00007ffd51a79080 R09: 0000000000000000 R10: 00005621f11352f2 R11: 0000000000000206 R12: 0000000000000000 R13: 0000000000000000 R14: 00005621f128b958 R15: 0000000080000000 Kernel Offset: disabled ---[ end Kernel panic - not syncing: softlockup: hung tasks ]---
All of these lockup reports have the call chain btrfs_clone_files() -> btrfs_clone() in common. btrfs_clone_files() calls btrfs_clone() with both source and destination extents locked and loops over the source extent to create the clones.
Conditionally reschedule in the btrfs_clone() loop, to give some time back to other processes.
--- fs/btrfs/ioctl.c | 2 ++ 1 file changed, 2 insertions(+)
fs/btrfs/ioctl.c +2 -0
@@ -3856,6 +3856,8 @@ process_slot: ret = -EINTR ; goto out; } + +cond_resched (); } ret =0 ;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 6/64 net: xfrm: fix a race condition during allocing spi
In reply to Greg Kroah-HartmanFrom: zhuoliang zhang <[email protected]>
[ Upstream commit a779d91314ca7208b7feb3ad817b62904397c56d ]
we found that the following race condition exists in xfrm_alloc_userspi flow:
user thread state_hash_work thread
---- ----xfrm_alloc_userspi()
__find_acq_core()
/*alloc new xfrm_state:x*/
xfrm_state_alloc()
/*schedule state_hash_work thread*/
xfrm_hash_grow_check() xfrm_hash_resize()
xfrm_alloc_spi /*hold lock*/
x->id.spi = htonl(spi) spin_lock_bh(&net->xfrm.xfrm_state_lock)
/*waiting lock release*/ xfrm_hash_transfer()
spin_lock_bh(&net->xfrm.xfrm_state_lock) /*add x into hlist:net->xfrm.state_byspi*/
hlist_add_head_rcu(&x->byspi)
spin_unlock_bh(&net->xfrm.xfrm_state_lock)
/*add x into hlist:net->xfrm.state_byspi 2 times*/
hlist_add_head_rcu(&x->byspi)1. a new state x is alloced in xfrm_state_alloc() and added into the bydst hlist in __find_acq_core() on the LHS;
2. on the RHS, state_hash_work thread travels the old bydst and tranfers every xfrm_state (include x) into the new bydst hlist and new byspi hlist;
3. user thread on the LHS gets the lock and adds x into the new byspi hlist again.
So the same xfrm_state (x) is added into the same list_hash (net->xfrm.state_byspi) 2 times that makes the list_hash become an inifite loop.
To fix the race, x->id.spi = htonl(spi) in the xfrm_alloc_spi() is moved to the back of spin_lock_bh, sothat state_hash_work thread no longer add x which id.spi is zero into the hash_list.
--- net/xfrm/xfrm_state.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
net/xfrm/xfrm_state.c +5 -3
@@ -1554,6 +1554,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)int err = -ENOENT ;__be32 minspi =htonl (low);__be32 maxspi =htonl (high); +__be32 newspi =0 ;u32 mark = x->mark.v & x->mark.m;spin_lock_bh (&x->lock);
@@ -1572,21 +1573,22 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)xfrm_state_put (x0); goto unlock; } - x->id.spi = minspi; + newspi = minspi; }else {u32 spi =0 ;for (h =0 ; h < high-low+1 ; h++) { spi = low +prandom_u32 ()%(high-low+1 ); x0 =xfrm_state_lookup (net, mark, &x->id.daddr,htonl (spi), x->id.proto, x->props.family);if (x0 ==NULL ) { - x->id.spi =htonl (spi); + newspi =htonl (spi);break ; }xfrm_state_put (x0); } } -if (x->id.spi) { +if (newspi) {spin_lock_bh (&net->xfrm.xfrm_state_lock); + x->id.spi = newspi; h =xfrm_spi_hash (net, &x->id.daddr, x->id.spi, x->id.proto, x->props.family);hlist_add_head (&x->byspi, net->xfrm.state_byspi+h);spin_unlock_bh (&net->xfrm.xfrm_state_lock);
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 7/64 perf tools: Add missing swap for ino_generation
In reply to Greg Kroah-HartmanFrom: Jiri Olsa <[email protected]>
[ Upstream commit fe01adb72356a4e2f8735e4128af85921ca98fa1 ]
We are missing swap for ino_generation field.
--- tools/perf/util/session.c | 1 + 1 file changed, 1 insertion(+)
tools/perf/util/session.c +1 -0
@@ -415,6 +415,7 @@ static void perf_event__mmap2_swap(union perf_event *event, event->mmap2.maj =bswap_32 (event->mmap2.maj); event->mmap2.min =bswap_32 (event->mmap2.min); event->mmap2.ino =bswap_64 (event->mmap2.ino); + event->mmap2.ino_generation =bswap_64 (event->mmap2.ino_generation);if (sample_id_all) {void *data = &event->mmap2.filename;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 8/64 ALSA: hda: prevent undefined shift in snd_hdac_ext_bus_get_link()
In reply to Greg Kroah-HartmanFrom: Dan Carpenter <[email protected]>
[ Upstream commit 158e1886b6262c1d1c96a18c85fac5219b8bf804 ]
This is harmless, but the "addr" comes from the user and it could lead to a negative shift or to shift wrapping if it's too high.
--- sound/hda/ext/hdac_ext_controller.c | 2 ++ 1 file changed, 2 insertions(+)
sound/hda/ext/hdac_ext_controller.c +2 -0
@@ -221,6 +221,8 @@ struct hdac_ext_link *snd_hdac_ext_bus_get_link(struct hdac_ext_bus *ebus,return NULL ;if (ebus->idx != bus_idx)return NULL ; +if (addr <0 || addr >31 ) +return NULL ;list_for_each_entry (hlink, &ebus->hlink_list, list) {for (i =0 ; i <HDA_MAX_CODECS ; i++) {
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 9/64 can: dev: can_get_echo_skb(): prevent call to kfree_skb() in hard IRQ context
In reply to Greg Kroah-HartmanFrom: Vincent Mailhol <[email protected]>
[ Upstream commit 2283f79b22684d2812e5c76fc2280aae00390365 ]
If a driver calls can_get_echo_skb() during a hardware IRQ (which is often, but not always, the case), the 'WARN_ON(in_irq)' in net/core/skbuff.c#skb_release_head_state() might be triggered, under network congestion circumstances, together with the potential risk of a NULL pointer dereference.
The root cause of this issue is the call to kfree_skb() instead of dev_kfree_skb_irq() in net/core/dev.c#enqueue_to_backlog().
This patch prevents the skb to be freed within the call to netif_rx() by incrementing its reference count with skb_get(). The skb is finally freed by one of the in-irq-context safe functions: dev_consume_skb_any() or dev_kfree_skb_any(). The "any" version is used because some drivers might call can_get_echo_skb() in a normal context.
The reason for this issue to occur is that initially, in the core network stack, loopback skb were not supposed to be received in hardware IRQ context. The CAN stack is an exeption.
This bug was previously reported back in 2017 in [1] but the proposed patch never got accepted.
While [1] directly modifies net/core/dev.c, we try to propose here a smoother modification local to CAN network stack (the assumption behind is that only CAN devices are affected by this issue).
[1] http://lore.kernel.org/r/[email protected]
--- drivers/net/can/dev.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/net/can/dev.c +5 -1
@@ -466,7 +466,11 @@ unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx)if (!skb)return 0 ; -netif_rx (skb); +skb_get (skb); +if (netif_rx (skb) ==NET_RX_SUCCESS ) +dev_consume_skb_any (skb); +else +dev_kfree_skb_any (skb);return len; }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 10/64 can: dev: __can_get_echo_skb(): fix real payload length return value for RTR frames
In reply to Greg Kroah-HartmanFrom: Oliver Hartkopp <[email protected]>
[ Upstream commit ed3320cec279407a86bc4c72edc4a39eb49165ec ]
The can_get_echo_skb() function returns the number of received bytes to be used for netdev statistics. In the case of RTR frames we get a valid (potential non-zero) data length value which has to be passed for further operations. But on the wire RTR frames have no payload length. Therefore the value to be used in the statistics has to be zero for RTR frames.
--- drivers/net/can/dev.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/net/can/dev.c +6 -2
@@ -439,9 +439,13 @@ struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8*/ struct sk_buff *skb = priv->echo_skb[idx];struct canfd_frame *cf = (struct canfd_frame *)skb->data; -u8 len = cf->len; - *len_ptr = len; +/* get the real payload length for netdev statistics */ +if (cf->can_id &CAN_RTR_FLAG ) + *len_ptr =0 ; +else + *len_ptr = cf->len; + priv->echo_skb[idx] =NULL ;return skb;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 11/64 can: can_create_echo_skb(): fix echo skb generation: always use skb_clone()
In reply to Greg Kroah-HartmanFrom: Oleksij Rempel <[email protected]>
[ Upstream commit 286228d382ba6320f04fa2e7c6fc8d4d92e428f4 ]
All user space generated SKBs are owned by a socket (unless injected into the key via AF_PACKET). If a socket is closed, all associated skbs will be cleaned up.
This leads to a problem when a CAN driver calls can_put_echo_skb() on a unshared SKB. If the socket is closed prior to the TX complete handler, can_get_echo_skb() and the subsequent delivering of the echo SKB to all registered callbacks, a SKB with a refcount of 0 is delivered.
To avoid the problem, in can_get_echo_skb() the original SKB is now always cloned, regardless of shared SKB or not. If the process exists it can now safely discard its SKBs, without disturbing the delivery of the echo SKB.
The problem shows up in the j1939 stack, when it clones the incoming skb, which detects the already 0 refcount.
We can easily reproduce this with following example:
testj1939 -B -r can0: &
cansend can0 1823ff40#0123
WARNING: CPU: 0 PID: 293 at lib/refcount.c:25 refcount_warn_saturate+0x108/0x174 refcount_t: addition on 0; use-after-free. Modules linked in: coda_vpu imx_vdoa videobuf2_vmalloc dw_hdmi_ahb_audio vcan CPU: 0 PID: 293 Comm: cansend Not tainted 5.5.0-rc6-00376-g9e20dcb7040d #1 Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree) Backtrace: [<c010f570>] (dump_backtrace) from [<c010f90c>] (show_stack+0x20/0x24) [<c010f8ec>] (show_stack) from [<c0c3e1a4>] (dump_stack+0x8c/0xa0) [<c0c3e118>] (dump_stack) from [<c0127fec>] (__warn+0xe0/0x108) [<c0127f0c>] (__warn) from [<c01283c8>] (warn_slowpath_fmt+0xa8/0xcc) [<c0128324>] (warn_slowpath_fmt) from [<c0539c0c>] (refcount_warn_saturate+0x108/0x174) [<c0539b04>] (refcount_warn_saturate) from [<c0ad2cac>] (j1939_can_recv+0x20c/0x210) [<c0ad2aa0>] (j1939_can_recv) from [<c0ac9dc8>] (can_rcv_filter+0xb4/0x268) [<c0ac9d14>] (can_rcv_filter) from [<c0aca2cc>] (can_receive+0xb0/0xe4) [<c0aca21c>] (can_receive) from [<c0aca348>] (can_rcv+0x48/0x98) [<c0aca300>] (can_rcv) from [<c09b1fdc>] (__netif_receive_skb_one_core+0x64/0x88) [<c09b1f78>] (__netif_receive_skb_one_core) from [<c09b2070>] (__netif_receive_skb+0x38/0x94) [<c09b2038>] (__netif_receive_skb) from [<c09b2130>] (netif_receive_skb_internal+0x64/0xf8) [<c09b20cc>] (netif_receive_skb_internal) from [<c09b21f8>] (netif_receive_skb+0x34/0x19c) [<c09b21c4>] (netif_receive_skb) from [<c0791278>] (can_rx_offload_napi_poll+0x58/0xb4)
--- include/linux/can/skb.h | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-)
include/linux/can/skb.h +8 -12
@@ -60,21 +60,17 @@ static inline void can_skb_set_owner(struct sk_buff *skb, struct sock *sk)*/ static inline struct sk_buff *can_create_echo_skb (struct sk_buff *skb) { -if (skb_shared (skb)) { -struct sk_buff *nskb =skb_clone (skb,GFP_ATOMIC ); +struct sk_buff *nskb; -if (likely (nskb)) { -can_skb_set_owner (nskb, skb->sk); -consume_skb (skb); -return nskb; - }else { -kfree_skb (skb); -return NULL ; - } + nskb =skb_clone (skb,GFP_ATOMIC ); +if (unlikely (!nskb)) { +kfree_skb (skb); +return NULL ; } -/* we can assume to have an unshared skb with proper owner */ -return skb; +can_skb_set_owner (nskb, skb->sk); +consume_skb (skb); +return nskb; }#endif /* !_CAN_SKB_H */
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 12/64 can: peak_usb: add range checking in decode operations
In reply to Greg Kroah-HartmanFrom: Dan Carpenter <[email protected]>
[ Upstream commit a6921dd524fe31d1f460c161d3526a407533b6db ]
These values come from skb->data so Smatch considers them untrusted. I believe Smatch is correct but I don't have a way to test this.
The usb_if->dev[] array has 2 elements but the index is in the 0-15 range without checks. The cfd->len can be up to 255 but the maximum valid size is CANFD_MAX_DLEN (64) so that could lead to memory corruption.
--- drivers/net/can/usb/peak_usb/pcan_usb_fd.c | 48 +++++++++++++++++----- 1 file changed, 37 insertions(+), 11 deletions(-)
drivers/net/can/usb/peak_usb/pcan_usb_fd.c +37 -11
@@ -475,12 +475,18 @@ static int pcan_usb_fd_decode_canmsg(struct pcan_usb_fd_if *usb_if, struct pucan_msg *rx_msg) {struct pucan_rx_msg *rm = (struct pucan_rx_msg *)rx_msg; -struct peak_usb_device *dev = usb_if->dev[pucan_msg_get_channel (rm)]; -struct net_device *netdev = dev->netdev; +struct peak_usb_device *dev; +struct net_device *netdev;struct canfd_frame *cfd;struct sk_buff *skb;const u16 rx_msg_flags =le16_to_cpu (rm->flags); +if (pucan_msg_get_channel (rm) >=ARRAY_SIZE (usb_if->dev)) +return -ENOMEM ; + + dev = usb_if->dev[pucan_msg_get_channel (rm)]; + netdev = dev->netdev; +if (rx_msg_flags &PUCAN_MSG_EXT_DATA_LEN ) {/* CANFD frame case */ skb =alloc_canfd_skb (netdev, &cfd);
@@ -527,15 +533,21 @@ static int pcan_usb_fd_decode_status(struct pcan_usb_fd_if *usb_if, struct pucan_msg *rx_msg) {struct pucan_status_msg *sm = (struct pucan_status_msg *)rx_msg; -struct peak_usb_device *dev = usb_if->dev[pucan_stmsg_get_channel (sm)]; -struct pcan_usb_fd_device *pdev = - container_of(dev, struct pcan_usb_fd_device, dev); +struct pcan_usb_fd_device *pdev;enum can_state new_state =CAN_STATE_ERROR_ACTIVE ;enum can_state rx_state, tx_state; -struct net_device *netdev = dev->netdev; +struct peak_usb_device *dev; +struct net_device *netdev;struct can_frame *cf;struct sk_buff *skb; +if (pucan_stmsg_get_channel (sm) >=ARRAY_SIZE (usb_if->dev)) +return -ENOMEM ; + + dev = usb_if->dev[pucan_stmsg_get_channel (sm)]; + pdev = container_of(dev, struct pcan_usb_fd_device, dev); + netdev = dev->netdev; +/* nothing should be sent while in BUS_OFF state */ if (dev->can.state ==CAN_STATE_BUS_OFF )return 0 ;
@@ -588,9 +600,14 @@ static int pcan_usb_fd_decode_error(struct pcan_usb_fd_if *usb_if, struct pucan_msg *rx_msg) {struct pucan_error_msg *er = (struct pucan_error_msg *)rx_msg; -struct peak_usb_device *dev = usb_if->dev[pucan_ermsg_get_channel (er)]; -struct pcan_usb_fd_device *pdev = - container_of(dev, struct pcan_usb_fd_device, dev); +struct pcan_usb_fd_device *pdev; +struct peak_usb_device *dev; + +if (pucan_ermsg_get_channel (er) >=ARRAY_SIZE (usb_if->dev)) +return -EINVAL ; + + dev = usb_if->dev[pucan_ermsg_get_channel (er)]; + pdev = container_of(dev, struct pcan_usb_fd_device, dev);/* keep a trace of tx and rx error counters for later use */ pdev->bec.txerr = er->tx_err_cnt;
@@ -604,11 +621,17 @@ static int pcan_usb_fd_decode_overrun(struct pcan_usb_fd_if *usb_if, struct pucan_msg *rx_msg) {struct pcan_ufd_ovr_msg *ov = (struct pcan_ufd_ovr_msg *)rx_msg; -struct peak_usb_device *dev = usb_if->dev[pufd_omsg_get_channel (ov)]; -struct net_device *netdev = dev->netdev; +struct peak_usb_device *dev; +struct net_device *netdev;struct can_frame *cf;struct sk_buff *skb; +if (pufd_omsg_get_channel (ov) >=ARRAY_SIZE (usb_if->dev)) +return -EINVAL ; + + dev = usb_if->dev[pufd_omsg_get_channel (ov)]; + netdev = dev->netdev; +/* allocate an skb to store the error frame */ skb =alloc_can_err_skb (netdev, &cf);if (!skb)
@@ -726,6 +749,9 @@ static int pcan_usb_fd_encode_msg(struct peak_usb_device *dev,u16 tx_msg_size, tx_msg_flags;u8 can_dlc; +if (cfd->len >CANFD_MAX_DLEN ) +return -EINVAL ; + tx_msg_size =ALIGN (sizeof (struct pucan_tx_msg ) + cfd->len,4 ); tx_msg->size =cpu_to_le16 (tx_msg_size); tx_msg->type =cpu_to_le16 (PUCAN_MSG_CAN_TX );
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 13/64 can: peak_usb: peak_usb_get_ts_time(): fix timestamp wrapping
In reply to Greg Kroah-HartmanFrom: Stephane Grosjean <[email protected]>
[ Upstream commit ecc7b4187dd388549544195fb13a11b4ea8e6a84 ]
Fabian Inostroza <[email protected]> has discovered a potential problem in the hardware timestamp reporting from the PCAN-USB USB CAN interface (only), related to the fact that a timestamp of an event may precede the timestamp used for synchronization when both records are part of the same USB packet. However, this case was used to detect the wrapping of the time counter.
This patch details and fixes the two identified cases where this problem can occur.
--- drivers/net/can/usb/peak_usb/pcan_usb_core.c | 51 ++++++++++++++++++-- 1 file changed, 46 insertions(+), 5 deletions(-)
drivers/net/can/usb/peak_usb/pcan_usb_core.c +46 -5
@@ -150,14 +150,55 @@ void peak_usb_get_ts_tv(struct peak_time_ref *time_ref, u32 ts,/* protect from getting timeval before setting now */ if (time_ref->tv_host.tv_sec >0 ) {u64 delta_us; +s64 delta_ts =0 ; + +/* General case: dev_ts_1 < dev_ts_2 < ts, with: +* +* - dev_ts_1 = previous sync timestamp +* - dev_ts_2 = last sync timestamp +* - ts = event timestamp +* - ts_period = known sync period (theoretical) +* ~ dev_ts2 - dev_ts1 +* *but*: +* +* - time counters wrap (see adapter->ts_used_bits) +* - sometimes, dev_ts_1 < ts < dev_ts2 +* +* "normal" case (sync time counters increase): +* must take into account case when ts wraps (tsw) +* +* < ts_period > < > +* | | | +* ---+--------+----+-------0-+--+--> +* ts_dev_1 | ts_dev_2 | +* ts tsw +*/ +if (time_ref->ts_dev_1 < time_ref->ts_dev_2) { +/* case when event time (tsw) wraps */ +if (ts < time_ref->ts_dev_1) + delta_ts =1 << time_ref->adapter->ts_used_bits; + +/* Otherwise, sync time counter (ts_dev_2) has wrapped: +* handle case when event time (tsn) hasn't. +* +* < ts_period > < > +* | | | +* ---+--------+--0-+---------+--+--> +* ts_dev_1 | ts_dev_2 | +* tsn ts +*/ + }else if (time_ref->ts_dev_1 < ts) { + delta_ts = -(1 << time_ref->adapter->ts_used_bits); + } - delta_us = ts - time_ref->ts_dev_2; -if (ts < time_ref->ts_dev_2) - delta_us &= (1 << time_ref->adapter->ts_used_bits) -1 ; +/* add delay between last sync and event timestamps */ + delta_ts += (signed int )(ts - time_ref->ts_dev_2); - delta_us += time_ref->ts_total; +/* add time from beginning to last sync */ + delta_ts += time_ref->ts_total; - delta_us *= time_ref->adapter->us_per_ts_scale; +/* convert ticks number into microseconds */ + delta_us = delta_ts * time_ref->adapter->us_per_ts_scale; delta_us >>= time_ref->adapter->us_per_ts_shift; *tv = time_ref->tv_host_0;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 14/64 Btrfs: fix missing error return if writeback for extent buffer never started
In reply to Greg Kroah-HartmanFrom: Filipe Manana <[email protected]>
[ Upstream commit 0607eb1d452d45c5ac4c745a9e9e0d95152ea9d0 ]
If lock_extent_buffer_for_io() fails, it returns a negative value, but its caller btree_write_cache_pages() ignores such error. This means that a call to flush_write_bio(), from lock_extent_buffer_for_io(), might have failed. We should make btree_write_cache_pages() notice such error values and stop immediatelly, making sure filemap_fdatawrite_range() returns an error to the transaction commit path. A failure from flush_write_bio() should also result in the endio callback end_bio_extent_buffer_writepage() being invoked, which sets the BTRFS_FS_*_ERR bits appropriately, so that there's no risk a transaction or log commit doesn't catch a writeback failure.
--- fs/btrfs/extent_io.c | 4 ++++ 1 file changed, 4 insertions(+)
fs/btrfs/extent_io.c +4 -0
@@ -4000,6 +4000,10 @@ int btree_write_cache_pages(struct address_space *mapping,if (!ret) {free_extent_buffer (eb);continue ; + }else if (ret <0 ) { + done =1 ; +free_extent_buffer (eb); +break ; } ret =write_one_eb (eb, fs_info, wbc, &epd);
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 15/64 pinctrl: devicetree: Avoid taking direct reference to device name string
In reply to Greg Kroah-HartmanFrom: Will Deacon <[email protected]>
commit be4c60b563edee3712d392aaeb0943a768df7023 upstream.
When populating the pinctrl mapping table entries for a device, the 'dev_name' field for each entry is initialised to point directly at the string returned by 'dev_name()' for the device and subsequently used by 'create_pinctrl()' when looking up the mappings for the device being probed.
This is unreliable in the presence of calls to 'dev_set_name()', which may reallocate the device name string leaving the pinctrl mappings with a dangling reference. This then leads to a use-after-free every time the name is dereferenced by a device probe:
| BUG: KASAN: invalid-access in strcmp+0x20/0x64 | Read of size 1 at addr 13ffffc153494b00 by task modprobe/590 | Pointer tag: [13], memory tag: [fe] | | Call trace: | __kasan_report+0x16c/0x1dc | kasan_report+0x10/0x18 | check_memory_region | __hwasan_load1_noabort+0x4c/0x54 | strcmp+0x20/0x64 | create_pinctrl+0x18c/0x7f4 | pinctrl_get+0x90/0x114 | devm_pinctrl_get+0x44/0x98 | pinctrl_bind_pins+0x5c/0x450 | really_probe+0x1c8/0x9a4 | driver_probe_device+0x120/0x1d8
Follow the example of sysfs, and duplicate the device name string before stashing it away in the pinctrl mapping entries.
--- drivers/pinctrl/devicetree.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-)
drivers/pinctrl/devicetree.c +20 -6
@@ -40,6 +40,13 @@ struct pinctrl_dt_map {static void dt_free_map (struct pinctrl_dev *pctldev,struct pinctrl_map *map,unsigned num_maps) { +int i; + +for (i =0 ; i < num_maps; ++i) { +kfree_const (map[i].dev_name); + map[i].dev_name =NULL ; + } +if (pctldev) {const struct pinctrl_ops *ops = pctldev->desc->pctlops; ops->dt_free_map (pctldev, map, num_maps);
@@ -73,7 +80,13 @@ static int dt_remember_or_free_map(struct pinctrl *p, const char *statename,/* Initialize common mapping table entry fields */ for (i =0 ; i < num_maps; i++) { - map[i].dev_name =dev_name (p->dev); +const char *devname; + + devname =kstrdup_const (dev_name (p->dev),GFP_KERNEL ); +if (!devname) + goto err_free_map; + + map[i].dev_name = devname; map[i].name = statename;if (pctldev) map[i].ctrl_dev_name =dev_name (pctldev->dev);
@@ -81,11 +94,8 @@ static int dt_remember_or_free_map(struct pinctrl *p, const char *statename,/* Remember the converted mapping table entries */ dt_map =kzalloc (sizeof (*dt_map),GFP_KERNEL ); -if (!dt_map) { -dev_err (p->dev,"failed to alloc struct pinctrl_dt_map\n" ); -dt_free_map (pctldev, map, num_maps); -return -ENOMEM ; - } +if (!dt_map) + goto err_free_map; dt_map->pctldev = pctldev; dt_map->map = map;
@@ -93,6 +103,10 @@ static int dt_remember_or_free_map(struct pinctrl *p, const char *statename,list_add_tail (&dt_map->node, &p->dt_maps);return pinctrl_register_map (map, num_maps, false); + +err_free_map: +dt_free_map (pctldev, map, num_maps); +return -ENOMEM ; }struct pinctrl_dev *of_pinctrl_get (struct device_node *np)
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 16/64 i40e: Wrong truncation from u16 to u8
In reply to Greg Kroah-HartmanFrom: Grzegorz Siwik <[email protected]>
commit c004804dceee9ca384d97d9857ea2e2795c2651d upstream.
In this patch fixed wrong truncation method from u16 to u8 during validation.
It was changed by changing u8 to u32 parameter in method declaration and arguments were changed to u32.
--- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +1 -1
@@ -203,7 +203,7 @@ static inline bool i40e_vc_isvalid_queue_id(struct i40e_vf *vf, u16 vsi_id,* * check for the valid vector id **/ -static inline bool i40e_vc_isvalid_vector_id (struct i40e_vf *vf,u8 vector_id) +static inline bool i40e_vc_isvalid_vector_id (struct i40e_vf *vf,u32 vector_id) {struct i40e_pf *pf = vf->pf;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 17/64 i40e: Fix of memory leak and integer truncation in i40e_virtchnl.c
In reply to Greg Kroah-HartmanFrom: Martyna Szapar <[email protected]>
commit 24474f2709af6729b9b1da1c5e160ab62e25e3a4 upstream.
Fixed possible memory leak in i40e_vc_add_cloud_filter function:
cfilter is being allocated and in some error conditions the function returns without freeing the memory.
Fix of integer truncation from u16 (type of queue_id value) to u8 when calling i40e_vc_isvalid_queue_id function.
[bwh: Backported to 4.4: i40e_vc_add_cloud_filter() does not exist
but the integer truncation is still possible]
--- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +1 -1
@@ -188,7 +188,7 @@ static inline bool i40e_vc_isvalid_vsi_id(struct i40e_vf *vf, u16 vsi_id)* check for the valid queue id **/ static inline bool i40e_vc_isvalid_queue_id (struct i40e_vf *vf,u16 vsi_id, -u8 qid) +u16 qid) {struct i40e_pf *pf = vf->pf;struct i40e_vsi *vsi =i40e_find_vsi_from_id (pf, vsi_id);
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 18/64 geneve: add transport ports in route lookup for geneve
In reply to Greg Kroah-HartmanFrom: Mark Gray <[email protected]>
commit 34beb21594519ce64a55a498c2fe7d567bc1ca20 upstream.
This patch adds transport ports information for route lookup so that IPsec can select Geneve tunnel traffic to do encryption. This is needed for OVS/OVN IPsec with encrypted Geneve tunnels.
This can be tested by configuring a host-host VPN using an IKE daemon and specifying port numbers. For example, for an Openswan-type configuration, the following parameters should be configured on both hosts and IPsec set up as-per normal:
$ cat /etc/ipsec.conf
conn in
...
left=$IP1
right=$IP2
...
leftprotoport=udp/6081
rightprotoport=udp
...
conn out
...
left=$IP1
right=$IP2
...
leftprotoport=udp
rightprotoport=udp/6081
...
The tunnel can then be setup using "ip" on both hosts (but changing the relevant IP addresses):
$ ip link add tun type geneve id 1000 remote $IP2 $ ip addr add 192.168.0.1/24 dev tun $ ip link set tun up
This can then be tested by pinging from $IP1:
$ ping 192.168.0.2
Without this patch the traffic is unencrypted on the wire.
[bwh: Backported to 4.4:
- Use geneve->dst_port instead of geneve->cfg.info.key.tp_dst
- Adjust context]
--- drivers/net/geneve.c | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-)
drivers/net/geneve.c +26 -10
@@ -711,7 +711,8 @@ static int geneve6_build_skb(struct dst_entry *dst, struct sk_buff *skb,static struct rtable *geneve_get_v4_rt (struct sk_buff *skb,struct net_device *dev,struct flowi4 *fl4, -struct ip_tunnel_info *info) +struct ip_tunnel_info *info, +__be16 dport,__be16 sport) {struct geneve_dev *geneve =netdev_priv (dev);struct rtable *rt =NULL ;
@@ -720,6 +721,8 @@ static struct rtable *geneve_get_v4_rt(struct sk_buff *skb,memset (fl4,0 ,sizeof (*fl4)); fl4->flowi4_mark = skb->mark; fl4->flowi4_proto =IPPROTO_UDP ; + fl4->fl4_dport = dport; + fl4->fl4_sport = sport;if (info) { fl4->daddr = info->key.u.ipv4.dst;
@@ -754,7 +757,8 @@ static struct rtable *geneve_get_v4_rt(struct sk_buff *skb,static struct dst_entry *geneve_get_v6_dst (struct sk_buff *skb,struct net_device *dev,struct flowi6 *fl6, -struct ip_tunnel_info *info) +struct ip_tunnel_info *info, +__be16 dport,__be16 sport) {struct geneve_dev *geneve =netdev_priv (dev);struct geneve_sock *gs6 = geneve->sock6;
@@ -764,6 +768,8 @@ static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb,memset (fl6,0 ,sizeof (*fl6)); fl6->flowi6_mark = skb->mark; fl6->flowi6_proto =IPPROTO_UDP ; + fl6->fl6_dport = dport; + fl6->fl6_sport = sport;if (info) { fl6->daddr = info->key.u.ipv6.dst;
@@ -834,13 +840,14 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, goto tx_error; } - rt =geneve_get_v4_rt (skb, dev, &fl4, info); + sport =udp_flow_src_port (geneve->net, skb,1 ,USHRT_MAX , true); + rt =geneve_get_v4_rt (skb, dev, &fl4, info, + geneve->dst_port, sport);if (IS_ERR (rt)) { err =PTR_ERR (rt); goto tx_error; } - sport =udp_flow_src_port (geneve->net, skb,1 ,USHRT_MAX , true);skb_reset_mac_header (skb);if (info) {
@@ -916,13 +923,14 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, } } - dst =geneve_get_v6_dst (skb, dev, &fl6, info); + sport =udp_flow_src_port (geneve->net, skb,1 ,USHRT_MAX , true); + dst =geneve_get_v6_dst (skb, dev, &fl6, info, + geneve->dst_port, sport);if (IS_ERR (dst)) { err =PTR_ERR (dst); goto tx_error; } - sport =udp_flow_src_port (geneve->net, skb,1 ,USHRT_MAX , true);skb_reset_mac_header (skb);if (info) {
@@ -1011,9 +1019,14 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)struct dst_entry *dst;struct flowi6 fl6;#endif +__be16 sport;if (ip_tunnel_info_af (info) ==AF_INET ) { - rt =geneve_get_v4_rt (skb, dev, &fl4, info); + sport =udp_flow_src_port (geneve->net, skb, +1 ,USHRT_MAX , true); + + rt =geneve_get_v4_rt (skb, dev, &fl4, info, + geneve->dst_port, sport);if (IS_ERR (rt))return PTR_ERR (rt);
@@ -1021,7 +1034,11 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) info->key.u.ipv4.src = fl4.saddr;#if IS_ENABLED (CONFIG_IPV6 ) } else if (ip_tunnel_info_af(info) == AF_INET6) { - dst =geneve_get_v6_dst (skb, dev, &fl6, info); + sport =udp_flow_src_port (geneve->net, skb, +1 ,USHRT_MAX , true); + + dst =geneve_get_v6_dst (skb, dev, &fl6, info, + geneve->dst_port, sport);if (IS_ERR (dst))return PTR_ERR (dst);
@@ -1032,8 +1049,7 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)return -EINVAL ; } - info->key.tp_src =udp_flow_src_port (geneve->net, skb, -1 ,USHRT_MAX , true); + info->key.tp_src = sport; info->key.tp_dst = geneve->dst_port;return 0 ; }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 19/64 ath9k_htc: Use appropriate rs_datalen type
In reply to Greg Kroah-HartmanFrom: Masashi Honma <[email protected]>
commit 5024f21c159f8c1668f581fff37140741c0b1ba9 upstream.
kernel test robot says:drivers/net/wireless/ath/ath9k/htc_drv_txrx.c:987:20: sparse: warning: incorrect type in assignment (different base types)drivers/net/wireless/ath/ath9k/htc_drv_txrx.c:987:20: sparse: expected restricted __be16 [usertype] rs_datalendrivers/net/wireless/ath/ath9k/htc_drv_txrx.c:987:20: sparse: got unsigned short [usertype]drivers/net/wireless/ath/ath9k/htc_drv_txrx.c:988:13: sparse: warning: restricted __be16 degrades to integer drivers/net/wireless/ath/ath9k/htc_drv_txrx.c:1001:13: sparse: warning: restricted __be16 degrades to integer
Indeed rs_datalen has host byte order, so modify it's own type.
--- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +1 -1
@@ -972,7 +972,7 @@ static bool ath9k_rx_prepare(struct ath9struct ath_htc_rx_status *rxstatus;struct ath_rx_status rx_stats;bool decrypt_error = false; -__be16 rs_datalen; +u16 rs_datalen;bool is_phyerr;if (skb->len <HTC_RX_FRAME_HEADER_SIZE ) {
Greg Kroah-Hartman
maintainerPATCH 20/64 usb: gadget: goku_udc: fix potential crashes in probe
In reply to Greg Kroah-HartmanFrom: Evgeny Novikov <[email protected]>
[ Upstream commit 0d66e04875c5aae876cf3d4f4be7978fa2b00523 ]
goku_probe() goes to error label "err" and invokes goku_remove() in case of failures of pci_enable_device(), pci_resource_start() and ioremap(). goku_remove() gets a device from pci_get_drvdata(pdev) and works with it without any checks, in particular it dereferences a corresponding pointer. But goku_probe() did not set this device yet. So, one can expect various crashes. The patch moves setting the device just after allocation of memory for it.
Found by Linux Driver Verification project (linuxtesting.org).
--- drivers/usb/gadget/udc/goku_udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/gadget/udc/goku_udc.c +1 -1
@@ -1773,6 +1773,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err; } +pci_set_drvdata (pdev, dev);spin_lock_init (&dev->lock); dev->pdev = pdev; dev->gadget.ops = &goku_ops;
@@ -1806,7 +1807,6 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) } dev->regs = (struct goku_udc_regs __iomem *) base; -pci_set_drvdata (pdev, dev);INFO (dev,"%s\n" , driver_desc);INFO (dev,"version: " DRIVER_VERSION " %s\n" ,dmastr ());INFO (dev,"irq %d, pci mem %p\n" , pdev->irq, base);
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 21/64 gfs2: Free rd_bits later in gfs2_clear_rgrpd to fix use-after-free
In reply to Greg Kroah-HartmanFrom: Bob Peterson <[email protected]>
[ Upstream commit d0f17d3883f1e3f085d38572c2ea8edbd5150172 ]
Function gfs2_clear_rgrpd calls kfree(rgd->rd_bits) before calling return_all_reservations, but return_all_reservations still dereferences rgd->rd_bits in __rs_deltree. Fix that by moving the call to kfree below the call to return_all_reservations.
--- fs/gfs2/rgrp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/gfs2/rgrp.c +1 -1
@@ -747,9 +747,9 @@ void gfs2_clear_rgrpd(struct gfs2_sbd *sdp) }gfs2_free_clones (rgd); +return_all_reservations (rgd);kfree (rgd->rd_bits); rgd->rd_bits =NULL ; -return_all_reservations (rgd);kmem_cache_free (gfs2_rgrpd_cachep, rgd); } }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 22/64 gfs2: check for live vs. read-only file system in gfs2_fitrim
In reply to Greg Kroah-HartmanFrom: Bob Peterson <[email protected]>
[ Upstream commit c5c68724696e7d2f8db58a5fce3673208d35c485 ]
Before this patch, gfs2_fitrim was not properly checking for a "live" file system. If the file system had something to trim and the file system was read-only (or spectator) it would start the trim, but when it starts the transaction, gfs2_trans_begin returns -EROFS (read-only file system) and it errors out. However, if the file system was already trimmed so there's no work to do, it never called gfs2_trans_begin. That code is bypassed so it never returns the error. Instead, it returns a good return code with 0 work. All this makes for inconsistent behavior:
The same fstrim command can return -EROFS in one case and 0 in another. This tripped up xfstests generic/537 which reports the error as:
+fstrim with unrecovered metadata just ate your filesystem
This patch adds a check for a "live" (iow, active journal, iow, RW) file system, and if not, returns the error properly.
--- fs/gfs2/rgrp.c | 3 +++ 1 file changed, 3 insertions(+)
fs/gfs2/rgrp.c +3 -0
@@ -1388,6 +1388,9 @@ int gfs2_fitrim(struct file *filp, void __user *argp)if (!capable (CAP_SYS_ADMIN ))return -EPERM ; +if (!test_bit (SDF_JOURNAL_LIVE , &sdp->sd_flags)) +return -EROFS ; +if (!blk_queue_discard (q))return -EOPNOTSUPP ;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 23/64 drm/amdgpu: perform srbm soft reset always on SDMA resume
In reply to Greg Kroah-HartmanFrom: Evan Quan <[email protected]>
[ Upstream commit 253475c455eb5f8da34faa1af92709e7bb414624 ]
This can address the random SDMA hang after pci config reset seen on Hawaii.
--- drivers/gpu/drm/amd/amdgpu/cik_sdma.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-)
drivers/gpu/drm/amd/amdgpu/cik_sdma.c +12 -15
@@ -1118,22 +1118,19 @@ static int cik_sdma_soft_reset(void *handle) {u32 srbm_soft_reset =0 ;struct amdgpu_device *adev = (struct amdgpu_device *)handle; -u32 tmp =RREG32 (mmSRBM_STATUS2); +u32 tmp; -if (tmp &SRBM_STATUS2__SDMA_BUSY_MASK ) { -/* sdma0 */ - tmp =RREG32 (mmSDMA0_F32_CNTL +SDMA0_REGISTER_OFFSET ); - tmp |=SDMA0_F32_CNTL__HALT_MASK ; -WREG32 (mmSDMA0_F32_CNTL +SDMA0_REGISTER_OFFSET , tmp); - srbm_soft_reset |=SRBM_SOFT_RESET__SOFT_RESET_SDMA_MASK ; - } -if (tmp &SRBM_STATUS2__SDMA1_BUSY_MASK ) { -/* sdma1 */ - tmp =RREG32 (mmSDMA0_F32_CNTL +SDMA1_REGISTER_OFFSET ); - tmp |=SDMA0_F32_CNTL__HALT_MASK ; -WREG32 (mmSDMA0_F32_CNTL +SDMA1_REGISTER_OFFSET , tmp); - srbm_soft_reset |=SRBM_SOFT_RESET__SOFT_RESET_SDMA1_MASK ; - } +/* sdma0 */ + tmp =RREG32 (mmSDMA0_F32_CNTL +SDMA0_REGISTER_OFFSET ); + tmp |=SDMA0_F32_CNTL__HALT_MASK ; +WREG32 (mmSDMA0_F32_CNTL +SDMA0_REGISTER_OFFSET , tmp); + srbm_soft_reset |=SRBM_SOFT_RESET__SOFT_RESET_SDMA_MASK ; + +/* sdma1 */ + tmp =RREG32 (mmSDMA0_F32_CNTL +SDMA1_REGISTER_OFFSET ); + tmp |=SDMA0_F32_CNTL__HALT_MASK ; +WREG32 (mmSDMA0_F32_CNTL +SDMA1_REGISTER_OFFSET , tmp); + srbm_soft_reset |=SRBM_SOFT_RESET__SOFT_RESET_SDMA1_MASK ;if (srbm_soft_reset) {cik_sdma_print_status ((void *)adev);
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 24/64 mac80211: fix use of skb payload instead of header
In reply to Greg Kroah-HartmanFrom: Johannes Berg <[email protected]>
[ Upstream commit 14f46c1e5108696ec1e5a129e838ecedf108c7bf ]
When ieee80211_skb_resize() is called from ieee80211_build_hdr() the skb has no 802.11 header yet, in fact it consist only of the payload as the ethernet frame is removed. As such, we're using the payload data for ieee80211_is_mgmt(), which is of course completely wrong. This didn't really hurt us because these are always data frames, so we could only have added more tailroom than we needed if we determined it was a management frame and sdata->crypto_tx_tailroom_needed_cnt was false.
However, syzbot found that of course there need not be any payload, so we're using at best uninitialized memory for the check.
Fix this to pass explicitly the kind of frame that we have instead of checking there, by replacing the "bool may_encrypt" argument with an argument that can carry the three possible states - it's not going to be encrypted, it's a management frame, or it's a data frame (and then we check sdata->crypto_tx_tailroom_needed_cnt).
--- net/mac80211/tx.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-)
net/mac80211/tx.c +23 -12
@@ -1594,19 +1594,24 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,/* device xmit handlers */ +enum ieee80211_encrypt { +ENCRYPT_NO , +ENCRYPT_MGMT , +ENCRYPT_DATA , +}; +static int ieee80211_skb_resize (struct ieee80211_sub_if_data *sdata,struct sk_buff *skb, -int head_need,bool may_encrypt) +int head_need, +enum ieee80211_encrypt encrypt) {struct ieee80211_local *local = sdata->local; -struct ieee80211_hdr *hdr;bool enc_tailroom;int tail_need =0 ; - hdr = (struct ieee80211_hdr *) skb->data; - enc_tailroom = may_encrypt && - (sdata->crypto_tx_tailroom_needed_cnt || -ieee80211_is_mgmt (hdr->frame_control)); + enc_tailroom = encrypt ==ENCRYPT_MGMT || + (encrypt ==ENCRYPT_DATA && + sdata->crypto_tx_tailroom_needed_cnt);if (enc_tailroom) { tail_need =IEEE80211_ENCRYPT_TAILROOM ;
@@ -1639,21 +1644,27 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,struct ieee80211_tx_info *info =IEEE80211_SKB_CB (skb);struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;int headroom; -bool may_encrypt; +enum ieee80211_encrypt encrypt; - may_encrypt = !(info->flags &IEEE80211_TX_INTFL_DONT_ENCRYPT ); +if (info->flags &IEEE80211_TX_INTFL_DONT_ENCRYPT ) + encrypt =ENCRYPT_NO ; +else if (ieee80211_is_mgmt (hdr->frame_control)) + encrypt =ENCRYPT_MGMT ; +else + encrypt =ENCRYPT_DATA ; headroom = local->tx_headroom; -if (may_encrypt) +if (encrypt !=ENCRYPT_NO ) headroom += sdata->encrypt_headroom; headroom -=skb_headroom (skb); headroom =max_t (int,0 , headroom); -if (ieee80211_skb_resize (sdata, skb, headroom, may_encrypt)) { +if (ieee80211_skb_resize (sdata, skb, headroom, encrypt)) {ieee80211_free_txskb (&local->hw, skb);return ; } +/* reload after potential resize */ hdr = (struct ieee80211_hdr *) skb->data; info->control.vif = &sdata->vif;
@@ -2346,7 +2357,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata, head_need += sdata->encrypt_headroom; head_need += local->tx_headroom; head_need =max_t (int,0 , head_need); -if (ieee80211_skb_resize (sdata, skb, head_need, true)) { +if (ieee80211_skb_resize (sdata, skb, head_need,ENCRYPT_DATA )) {ieee80211_free_txskb (&local->hw, skb); skb =NULL ;return ERR_PTR (-ENOMEM );
@@ -2756,7 +2767,7 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,if (unlikely (ieee80211_skb_resize (sdata, skb,max_t (int, extra_head + hw_headroom -skb_headroom (skb),0 ), - false))) { +ENCRYPT_NO ))) {kfree_skb (skb);return true; }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 25/64 mac80211: always wind down STA state
In reply to Greg Kroah-HartmanFrom: Johannes Berg <[email protected]>
[ Upstream commit dcd479e10a0510522a5d88b29b8f79ea3467d501 ]
When (for example) an IBSS station is pre-moved to AUTHORIZED before it's inserted, and then the insertion fails, we don't clean up the fast RX/TX states that might already have been created, since we don't go through all the state transitions again on the way down.
Do that, if it hasn't been done already, when the station is freed. I considered only freeing the fast TX/RX state there, but we might add more state so it's more robust to wind down the state properly.
Note that we warn if the station was ever inserted, it should have been properly cleaned up in that case, and the driver will probably not like things happening out of order.
--- net/mac80211/sta_info.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
net/mac80211/sta_info.c +18 -0
@@ -242,6 +242,24 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata,*/ void sta_info_free (struct ieee80211_local *local,struct sta_info *sta) { +/* +* If we had used sta_info_pre_move_state() then we might not +* have gone through the state transitions down again, so do +* it here now (and warn if it's inserted). +* +* This will clear state such as fast TX/RX that may have been +* allocated during state transitions. +*/ +while (sta->sta_state >IEEE80211_STA_NONE ) { +int ret; + +WARN_ON_ONCE (test_sta_flag (sta,WLAN_STA_INSERTED )); + + ret =sta_info_move_state (sta, sta->sta_state -1 ); +if (WARN_ONCE (ret,"sta_info_move_state() returned %d\n" , ret)) +break ; + } +if (sta->rate_ctrl)rate_control_free_sta (sta);
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 26/64 cfg80211: regulatory: Fix inconsistent format argument
In reply to Greg Kroah-HartmanFrom: Ye Bin <[email protected]>
[ Upstream commit db18d20d1cb0fde16d518fb5ccd38679f174bc04 ]
Fix follow warning:
[net/wireless/reg.c:3619]: (warning) %d in format string (no. 2) requires 'int' but the argument type is 'unsigned int'.
--- net/wireless/reg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/wireless/reg.c +1 -1
@@ -2775,7 +2775,7 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd) power_rule = ®_rule->power_rule;if (reg_rule->flags &NL80211_RRF_AUTO_BW ) -snprintf (bw,sizeof (bw),"%d KHz, %d KHz AUTO" , +snprintf (bw,sizeof (bw),"%d KHz, %u KHz AUTO" , freq_range->max_bandwidth_khz,reg_get_max_bandwidth (rd, reg_rule));else
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 27/64 iommu/amd: Increase interrupt remapping table limit to 512 entries
In reply to Greg Kroah-HartmanFrom: Suravee Suthikulpanit <[email protected]>
[ Upstream commit 73db2fc595f358460ce32bcaa3be1f0cce4a2db1 ]
Certain device drivers allocate IO queues on a per-cpu basis. On AMD EPYC platform, which can support up-to 256 cpu threads, this can exceed the current MAX_IRQ_PER_TABLE limit of 256, and result in the error message:
AMD-Vi: Failed to allocate IRTE
This has been observed with certain NVME devices.
AMD IOMMU hardware can actually support upto 512 interrupt remapping table entries. Therefore, update the driver to match the hardware limit.
Please note that this also increases the size of interrupt remapping table to 8KB per device when using the 128-bit IRTE format.
--- drivers/iommu/amd_iommu_types.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/iommu/amd_iommu_types.h +5 -1
@@ -351,7 +351,11 @@ extern bool amd_iommu_np_cache;/* Only true if all IOMMUs support device IOTLBs */ extern bool amd_iommu_iotlb_sup; -#define MAX_IRQS_PER_TABLE 256 +/* +* AMD IOMMU hardware only support 512 IRTEs despite +* the architectural limitation of 2048 entries. +*/ +#define MAX_IRQS_PER_TABLE 512#define IRQ_TABLE_ALIGNMENT 128struct irq_remap_table {
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 28/64 xfs: fix a missing unlock on error in xfs_fs_map_blocks
In reply to Greg Kroah-HartmanFrom: Christoph Hellwig <[email protected]>
[ Upstream commit 2bd3fa793aaa7e98b74e3653fdcc72fa753913b5 ]
We also need to drop the iolock when invalidate_inode_pages2 fails, not only on all other error or successful cases.
--- fs/xfs/xfs_pnfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/xfs/xfs_pnfs.c +1 -1
@@ -162,7 +162,7 @@ xfs_fs_map_blocks( goto out_unlock; error =invalidate_inode_pages2 (inode->i_mapping);if (WARN_ON_ONCE (error)) -return error; + goto out_unlock; end_fsb =XFS_B_TO_FSB (mp, (xfs_ufsize_t )offset + length); offset_fsb =XFS_B_TO_FSBT (mp, offset);
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 29/64 of/address: Fix of_node memory leak in of_dma_is_coherent
In reply to Greg Kroah-HartmanFrom: Evan Nimmo <[email protected]>
[ Upstream commit a5bea04fcc0b3c0aec71ee1fd58fd4ff7ee36177 ]
Commit dabf6b36b83a ("of: Add OF_DMA_DEFAULT_COHERENT & select it on powerpc") added a check to of_dma_is_coherent which returns early if OF_DMA_DEFAULT_COHERENT is enabled. This results in the of_node_put() being skipped causing a memory leak. Moved the of_node_get() below this check so we now we only get the node if OF_DMA_DEFAULT_COHERENT is not enabled.
--- drivers/of/address.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/of/address.c +3 -1
@@ -1014,11 +1014,13 @@ EXPORT_SYMBOL_GPL(of_dma_get_range);*/ bool of_dma_is_coherent (struct device_node *np) { -struct device_node *node =of_node_get (np); +struct device_node *node;if (IS_ENABLED (CONFIG_OF_DMA_DEFAULT_COHERENT ))return true; + node =of_node_get (np); +while (node) {if (of_property_read_bool (node,"dma-coherent" )) {of_node_put (node);
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 30/64 cosa: Add missing kfree in error path of cosa_write
In reply to Greg Kroah-HartmanFrom: Wang Hai <[email protected]>
[ Upstream commit 52755b66ddcef2e897778fac5656df18817b59ab ]
If memory allocation for 'kbuf' succeed, cosa_write() doesn't have a corresponding kfree() in exception handling. Thus add kfree() for this function implementation.
--- drivers/net/wan/cosa.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/wan/cosa.c +1 -0
@@ -903,6 +903,7 @@ static ssize_t cosa_write(struct file *file, chan->tx_status =1 ;spin_unlock_irqrestore (&cosa->lock, flags);up (&chan->wsem); +kfree (kbuf);return -ERESTARTSYS ; } }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 31/64 perf: Fix get_recursion_context()
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
[ Upstream commit ce0f17fc93f63ee91428af10b7b2ddef38cd19e5 ]
One should use in_serving_softirq() to detect SoftIRQ context.
--- kernel/events/internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/events/internal.h +1 -1
@@ -193,7 +193,7 @@ static inline int get_recursion_context(int *recursion) rctx =3 ; else if (in_irq()) rctx =2 ; - else if (in_softirq()) + else if (in_serving_softirq()) rctx =1 ; else rctx =0 ;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 32/64 ext4: correctly report "not supported" for {usr,grp}jquota when !CONFIG_QUOTA
In reply to Greg Kroah-HartmanFrom: Kaixu Xia <[email protected]>
commit 174fe5ba2d1ea0d6c5ab2a7d4aa058d6d497ae4d upstream.
The macro MOPT_Q is used to indicates the mount option is related to quota stuff and is defined to be MOPT_NOSUPPORT when CONFIG_QUOTA is disabled. Normally the quota options are handled explicitly, so it didn't matter that the MOPT_STRING flag was missing, even though the usrjquota and grpjquota mount options take a string argument. It's important that's present in the !CONFIG_QUOTA case, since without MOPT_STRING, the mount option matcher will match usrjquota= followed by an integer, and will otherwise skip the table entry, and so "mount option not supported" error message is never reported.
[ Fixed up the commit description to better explain why the fix
works. --TYT ]
--- fs/ext4/super.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/ext4/super.c +2 -2
@@ -1452,8 +1452,8 @@ static const struct mount_opts { MOPT_SET | MOPT_Q}, {Opt_noquota, (EXT4_MOUNT_QUOTA |EXT4_MOUNT_USRQUOTA | EXT4_MOUNT_GRPQUOTA), MOPT_CLEAR | MOPT_Q}, - {Opt_usrjquota, 0, MOPT_Q}, - {Opt_grpjquota, 0, MOPT_Q}, + {Opt_usrjquota, 0, MOPT_Q | MOPT_STRING}, + {Opt_grpjquota, 0, MOPT_Q | MOPT_STRING}, {Opt_offusrjquota, 0, MOPT_Q}, {Opt_offgrpjquota, 0, MOPT_Q}, {Opt_jqfmt_vfsold, QFMT_VFS_OLD, MOPT_QFMT},
Greg Kroah-Hartman
maintainerPATCH 33/64 ext4: unlock xattr_sem properly in ext4_inline_data_truncate()
In reply to Greg Kroah-HartmanFrom: Joseph Qi <[email protected]>
commit 7067b2619017d51e71686ca9756b454de0e5826a upstream.
It takes xattr_sem to check inline data again but without unlock it in case not have. So unlock it before return.
--- fs/ext4/inline.c | 1 + 1 file changed, 1 insertion(+)
fs/ext4/inline.c +1 -0
@@ -1892,6 +1892,7 @@ void ext4_inline_data_truncate(struct inext4_write_lock_xattr (inode, &no_expand);if (!ext4_has_inline_data (inode)) { +ext4_write_unlock_xattr (inode, &no_expand); *has_inline =0 ;ext4_journal_stop (handle);return ;
Greg Kroah-Hartman
maintainerPATCH 34/64 usb: cdc-acm: Add DISABLE_ECHO for Renesas USB Download mode
In reply to Greg Kroah-HartmanFrom: Chris Brandt <[email protected]>
commit 6d853c9e4104b4fc8d55dc9cd3b99712aa347174 upstream.
Renesas R-Car and RZ/G SoCs have a firmware download mode over USB. However, on reset a banner string is transmitted out which is not expected to be echoed back and will corrupt the protocol.
--- drivers/usb/class/cdc-acm.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/usb/class/cdc-acm.c +9 -0
@@ -1693,6 +1693,15 @@ static const struct usb_device_id acm_id { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */ .driver_info =NO_UNION_NORMAL ,/* has no union descriptor */ }, + { USB_DEVICE(0x045b, 0x023c), /* Renesas USB Download mode */ + .driver_info = DISABLE_ECHO, /* Don't echo banner */ + }, + { USB_DEVICE(0x045b, 0x0248), /* Renesas USB Download mode */ + .driver_info = DISABLE_ECHO, /* Don't echo banner */ + }, + { USB_DEVICE(0x045b, 0x024D), /* Renesas USB Download mode */ + .driver_info = DISABLE_ECHO, /* Don't echo banner */ + }, { USB_DEVICE(0x0e8d, 0x0003), /* FIREFLY, MediaTek Inc; [email protected] */ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ },
Greg Kroah-Hartman
maintainerPATCH 35/64 mei: protect mei_cl_mtu from null dereference
In reply to Greg Kroah-HartmanFrom: Alexander Usyskin <[email protected]>
commit bcbc0b2e275f0a797de11a10eff495b4571863fc upstream.
A receive callback is queued while the client is still connected but can still be called after the client was disconnected. Upon disconnect cl->me_cl is set to NULL, hence we need to check that ME client is not-NULL in mei_cl_mtu to avoid
null dereference.
--- drivers/misc/mei/client.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/misc/mei/client.h +2 -2
@@ -156,11 +156,11 @@ static inline u8 mei_cl_me_id(const stru* * @cl: host client * -* Return: mtu +* Return: mtu or 0 if client is not connected */ static inline size_t mei_cl_mtu (const struct mei_cl *cl) { -return cl->me_cl->props.max_msg_length; +return cl->me_cl ? cl->me_cl->props.max_msg_length :0 ; }/**
Greg Kroah-Hartman
maintainerPATCH 36/64 ocfs2: initialize ip_next_orphan
In reply to Greg Kroah-HartmanFrom: Wengang Wang <[email protected]>
commit f5785283dd64867a711ca1fb1f5bb172f252ecdf upstream.
Though problem if found on a lower 4.1.12 kernel, I think upstream has same issue.
In one node in the cluster, there is the following callback trace:
# cat /proc/21473/stack __ocfs2_cluster_lock.isra.36+0x336/0x9e0 [ocfs2] ocfs2_inode_lock_full_nested+0x121/0x520 [ocfs2] ocfs2_evict_inode+0x152/0x820 [ocfs2] evict+0xae/0x1a0 iput+0x1c6/0x230 ocfs2_orphan_filldir+0x5d/0x100 [ocfs2] ocfs2_dir_foreach_blk+0x490/0x4f0 [ocfs2] ocfs2_dir_foreach+0x29/0x30 [ocfs2] ocfs2_recover_orphans+0x1b6/0x9a0 [ocfs2] ocfs2_complete_recovery+0x1de/0x5c0 [ocfs2] process_one_work+0x169/0x4a0 worker_thread+0x5b/0x560 kthread+0xcb/0xf0 ret_from_fork+0x61/0x90
The above stack is not reasonable, the final iput shouldn't happen in ocfs2_orphan_filldir() function. Looking at the code,
2067 /* Skip inodes which are already added to recover list, since dio may
2068 * happen concurrently with unlink/rename */
2069 if (OCFS2_I(iter)->ip_next_orphan) {
2070 iput(iter);
2071 return 0;
2072 }
2073The logic thinks the inode is already in recover list on seeing ip_next_orphan is non-NULL, so it skip this inode after dropping a reference which incremented in ocfs2_iget().
While, if the inode is already in recover list, it should have another reference and the iput() at line 2070 should not be the final iput (dropping the last reference). So I don't think the inode is really in the recover list (no vmcore to confirm).
Note that ocfs2_queue_orphans(), though not shown up in the call back trace, is holding cluster lock on the orphan directory when looking up for unlinked inodes. The on disk inode eviction could involve a lot of IOs which may need long time to finish. That means this node could hold the cluster lock for very long time, that can lead to the lock requests (from other nodes) to the orhpan directory hang for long time.
Looking at more on ip_next_orphan, I found it's not initialized when allocating a new ocfs2_inode_info structure.
This causes te reflink operations from some nodes hang for very long time waiting for the cluster lock on the orphan directory.
Fix: initialize ip_next_orphan as NULL.
--- fs/ocfs2/super.c | 1 + 1 file changed, 1 insertion(+)
fs/ocfs2/super.c +1 -0
@@ -1751,6 +1751,7 @@ static void ocfs2_inode_init_once(void * oi->ip_blkno =0ULL ; oi->ip_clusters =0 ; + oi->ip_next_orphan =NULL ;ocfs2_resv_init_once (&oi->ip_la_data_resv);
Greg Kroah-Hartman
maintainerPATCH 37/64 dont dump the threads that had been already exiting when zapped.
In reply to Greg Kroah-HartmanFrom: Al Viro <[email protected]>
commit 77f6ab8b7768cf5e6bdd0e72499270a0671506ee upstream.
Coredump logics needs to report not only the registers of the dumping thread, but (since 2.5.43) those of other threads getting killed.
Doing that might require extra state saved on the stack in asm glue at kernel entry; signal delivery logics does that (we need to be able to save sigcontext there, at the very least) and so does seccomp.
That covers all callers of do_coredump(). Secondary threads get hit with SIGKILL and caught as soon as they reach exit_mm(), which normally happens in signal delivery, so those are also fine most of the time. Unfortunately, it is possible to end up with secondary zapped when it has already entered exit(2) (or, worse yet, is oopsing). In those cases we reach exit_mm() when mm->core_state is already set, but the stack contents is not what we would have in signal delivery.
At least on two architectures (alpha and m68k) it leads to infoleaks - we end up with a chunk of kernel stack written into coredump, with the contents consisting of normal C stack frames of the call chain leading to exit_mm() instead of the expected copy of userland registers. In case of alpha we leak 312 bytes of stack. Other architectures (including the regset-using ones) might have similar problems - the normal user of regsets is ptrace and the state of tracee at the time of such calls is special in the same way signal delivery is.
Note that had the zapper gotten to the exiting thread slightly later, it wouldn't have been included into coredump anyway - we skip the threads that have already cleared their ->mm. So let's pretend that zapper always loses the race. IOW, have exit_mm() only insert into the dumper list if we'd gotten there from handling a fatal signal[*]
As the result, the callers of do_exit() that have *not* gone through get_signal() are not seen by coredump logics as secondary threads. Which excludes voluntary exit()/oopsen/traps/etc. The dumper thread itself is unaffected by that, so seccomp is fine.
[*] originally I intended to add a new flag in tsk->flags, but ebiederman pointed out that PF_SIGNALED is already doing just what we need.
History-tree: https://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git
--- kernel/exit.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
kernel/exit.c +4 -1
@@ -408,7 +408,10 @@ static void exit_mm(struct task_struct *up_read (&mm->mmap_sem); self.task = tsk; - self.next =xchg (&core_state->dumper.next, &self); +if (self.task->flags &PF_SIGNALED ) + self.next =xchg (&core_state->dumper.next, &self); +else + self.task =NULL ;/* * Implies mb(), the result of xchg() must be visible * to core_state->dumper.
Greg Kroah-Hartman
maintainerPATCH 38/64 drm/gma500: Fix out-of-bounds access to struct drm_device.vblank[]
In reply to Greg Kroah-HartmanFrom: Thomas Zimmermann <[email protected]>
commit 06ad8d339524bf94b89859047822c31df6ace239 upstream.
The gma500 driver expects 3 pipelines in several it's IRQ functions. Accessing struct drm_device.vblank[], this fails with devices that only have 2 pipelines. An example KASAN report is shown below.
[ 62.267688] ================================================================== [ 62.268856] BUG: KASAN: slab-out-of-bounds in psb_irq_postinstall+0x250/0x3c0 [gma500_gfx] [ 62.269450] Read of size 1 at addr ffff8880012bc6d0 by task systemd-udevd/285 [ 62.269949] [ 62.270192] CPU: 0 PID: 285 Comm: systemd-udevd Tainted: G E 5.10.0-rc1-1-default+ #572 [ 62.270807] Hardware name: /DN2800MT, BIOS MTCDT10N.86A.0164.2012.1213.1024 12/13/2012 [ 62.271366] Call Trace: [ 62.271705] dump_stack+0xae/0xe5 [ 62.272180] print_address_description.constprop.0+0x17/0xf0 [ 62.272987] ? psb_irq_postinstall+0x250/0x3c0 [gma500_gfx] [ 62.273474] __kasan_report.cold+0x20/0x38 [ 62.273989] ? psb_irq_postinstall+0x250/0x3c0 [gma500_gfx] [ 62.274460] kasan_report+0x3a/0x50 [ 62.274891] psb_irq_postinstall+0x250/0x3c0 [gma500_gfx] [ 62.275380] drm_irq_install+0x131/0x1f0 <...> [ 62.300751] Allocated by task 285: [ 62.301223] kasan_save_stack+0x1b/0x40 [ 62.301731] __kasan_kmalloc.constprop.0+0xbf/0xd0 [ 62.302293] drmm_kmalloc+0x55/0x100 [ 62.302773] drm_vblank_init+0x77/0x210
Resolve the issue by only handling vblank entries up to the number of CRTCs.
I'm adding a Fixes tag for reference, although the bug has been present since the driver's initial commit.
--- drivers/gpu/drm/gma500/psb_irq.c | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-)
drivers/gpu/drm/gma500/psb_irq.c +12 -22
@@ -350,6 +350,7 @@ int psb_irq_postinstall(struct drm_devic {struct drm_psb_private *dev_priv = dev->dev_private;unsigned long irqflags; +unsigned int i;spin_lock_irqsave (&dev_priv->irqmask_lock, irqflags);
@@ -362,20 +363,12 @@ int psb_irq_postinstall(struct drm_devicPSB_WVDC32 (dev_priv->vdc_irq_mask,PSB_INT_ENABLE_R );PSB_WVDC32 (0xFFFFFFFF ,PSB_HWSTAM ); -if (dev->vblank[0 ].enabled) -psb_enable_pipestat (dev_priv,0 ,PIPE_VBLANK_INTERRUPT_ENABLE ); -else -psb_disable_pipestat (dev_priv,0 ,PIPE_VBLANK_INTERRUPT_ENABLE ); - -if (dev->vblank[1 ].enabled) -psb_enable_pipestat (dev_priv,1 ,PIPE_VBLANK_INTERRUPT_ENABLE ); -else -psb_disable_pipestat (dev_priv,1 ,PIPE_VBLANK_INTERRUPT_ENABLE ); - -if (dev->vblank[2 ].enabled) -psb_enable_pipestat (dev_priv,2 ,PIPE_VBLANK_INTERRUPT_ENABLE ); -else -psb_disable_pipestat (dev_priv,2 ,PIPE_VBLANK_INTERRUPT_ENABLE ); +for (i =0 ; i < dev->num_crtcs; ++i) { +if (dev->vblank[i].enabled) +psb_enable_pipestat (dev_priv, i,PIPE_VBLANK_INTERRUPT_ENABLE ); +else +psb_disable_pipestat (dev_priv, i,PIPE_VBLANK_INTERRUPT_ENABLE ); + }if (dev_priv->ops->hotplug_enable) dev_priv->ops->hotplug_enable (dev, true);
@@ -388,6 +381,7 @@ void psb_irq_uninstall(struct drm_device {struct drm_psb_private *dev_priv = dev->dev_private;unsigned long irqflags; +unsigned int i;spin_lock_irqsave (&dev_priv->irqmask_lock, irqflags);
@@ -396,14 +390,10 @@ void psb_irq_uninstall(struct drm_devicePSB_WVDC32 (0xFFFFFFFF ,PSB_HWSTAM ); -if (dev->vblank[0 ].enabled) -psb_disable_pipestat (dev_priv,0 ,PIPE_VBLANK_INTERRUPT_ENABLE ); - -if (dev->vblank[1 ].enabled) -psb_disable_pipestat (dev_priv,1 ,PIPE_VBLANK_INTERRUPT_ENABLE ); - -if (dev->vblank[2 ].enabled) -psb_disable_pipestat (dev_priv,2 ,PIPE_VBLANK_INTERRUPT_ENABLE ); +for (i =0 ; i < dev->num_crtcs; ++i) { +if (dev->vblank[i].enabled) +psb_disable_pipestat (dev_priv, i,PIPE_VBLANK_INTERRUPT_ENABLE ); + } dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG | _PSB_IRQ_MSVDX_FLAG |
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Greg Kroah-Hartman
maintainerPATCH 39/64 pinctrl: amd: use higher precision for 512 RtcClk
In reply to Greg Kroah-HartmanFrom: Coiby Xu <[email protected]>
commit c64a6a0d4a928c63e5bc3b485552a8903a506c36 upstream.
RTC is 32.768kHz thus 512 RtcClk equals 15625 usec. The documentation likely has dropped precision and that's why the driver mistakenly took the slightly deviated value.
--- drivers/pinctrl/pinctrl-amd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pinctrl/pinctrl-amd.c +1 -1
@@ -144,7 +144,7 @@ static int amd_gpio_set_debounce(struct pin_reg |=BIT (DB_TMR_OUT_UNIT_OFF ); pin_reg &= ~BIT (DB_TMR_LARGE_OFF ); }else if (debounce <250000 ) { - time = debounce /15600 ; + time = debounce /15625 ; pin_reg |= time &DB_TMR_OUT_MASK ; pin_reg &= ~BIT (DB_TMR_OUT_UNIT_OFF ); pin_reg |=BIT (DB_TMR_LARGE_OFF );
Greg Kroah-Hartman
maintainerPATCH 40/64 pinctrl: amd: fix incorrect way to disable debounce filter
In reply to Greg Kroah-HartmanFrom: Coiby Xu <[email protected]>
commit 06abe8291bc31839950f7d0362d9979edc88a666 upstream.
The correct way to disable debounce filter is to clear bit 5 and 6 of the register.
--- drivers/pinctrl/pinctrl-amd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/pinctrl/pinctrl-amd.c +2 -2
@@ -154,14 +154,14 @@ static int amd_gpio_set_debounce(struct pin_reg |=BIT (DB_TMR_OUT_UNIT_OFF ); pin_reg |=BIT (DB_TMR_LARGE_OFF ); }else { - pin_reg &= ~DB_CNTRl_MASK; + pin_reg &= ~(DB_CNTRl_MASK <<DB_CNTRL_OFF ); ret = -EINVAL ; } }else { pin_reg &= ~BIT (DB_TMR_OUT_UNIT_OFF ); pin_reg &= ~BIT (DB_TMR_LARGE_OFF ); pin_reg &= ~DB_TMR_OUT_MASK ; - pin_reg &= ~DB_CNTRl_MASK; + pin_reg &= ~(DB_CNTRl_MASK <<DB_CNTRL_OFF ); }writel (pin_reg, gpio_dev->base + offset *4 );spin_unlock_irqrestore (&gpio_dev->lock, flags);
Greg Kroah-Hartman
maintainerPATCH 41/64 swiotlb: fix "x86: Dont panic if can not alloc buffer for swiotlb"
In reply to Greg Kroah-HartmanFrom: Stefano Stabellini <[email protected]>
commit e9696d259d0fb5d239e8c28ca41089838ea76d13 upstream.
kernel/dma/swiotlb.c:swiotlb_init gets called first and tries to allocate a buffer for the swiotlb. It does so by calling
memblock_alloc_low(PAGE_ALIGN(bytes), PAGE_SIZE);
If the allocation must fail, no_iotlb_memory is set.
Later during initialization swiotlb-xen comes in (drivers/xen/swiotlb-xen.c:xen_swiotlb_init) and given that io_tlb_start is != 0, it thinks the memory is ready to use when actually it is not.
When the swiotlb is actually needed, swiotlb_tbl_map_single gets called and since no_iotlb_memory is set the kernel panics.
Instead, if swiotlb-xen.c:xen_swiotlb_init knew the swiotlb hadn't been initialized, it would do the initialization itself, which might still succeed.
Fix the panic by setting io_tlb_start to 0 on swiotlb initialization failure, and also by setting no_iotlb_memory to false on swiotlb initialization success.
--- lib/swiotlb.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
lib/swiotlb.c +5 -1
@@ -195,6 +195,7 @@ int __init swiotlb_init_with_tbl(char *t io_tlb_orig_addr[i] =INVALID_PHYS_ADDR ; } io_tlb_index =0 ; + no_iotlb_memory = false;if (verbose)swiotlb_print_info ();
@@ -225,9 +226,11 @@ swiotlb_init(int verbose)if (vstart && !swiotlb_init_with_tbl (vstart, io_tlb_nslabs, verbose))return ; -if (io_tlb_start) +if (io_tlb_start) {memblock_free_early (io_tlb_start,PAGE_ALIGN (io_tlb_nslabs <<IO_TLB_SHIFT )); + io_tlb_start =0 ; + }pr_warn ("Cannot allocate buffer" ); no_iotlb_memory = true; }
@@ -326,6 +329,7 @@ swiotlb_late_init_with_tbl(char *tlb, un io_tlb_orig_addr[i] =INVALID_PHYS_ADDR ; } io_tlb_index =0 ; + no_iotlb_memory = false;swiotlb_print_info ();
Greg Kroah-Hartman
maintainerPATCH 42/64 IPv6: Set SIT tunnel hard_header_len to zero
In reply to Greg Kroah-HartmanFrom: Oliver Herms <[email protected]>
[ Upstream commit 8ef9ba4d666614497a057d09b0a6eafc1e34eadf ]
Due to the legacy usage of hard_header_len for SIT tunnels while already using infrastructure from net/ipv4/ip_tunnel.c the calculation of the path MTU in tnl_update_pmtu is incorrect. This leads to unnecessary creation of MTU exceptions for any flow going over a SIT tunnel.
As SIT tunnels do not have a header themsevles other than their transport (L3, L2) headers we're leaving hard_header_len set to zero as tnl_update_pmtu is already taking care of the transport headers sizes.
This will also help avoiding unnecessary IPv6 GC runs and spinlock contention seen when using SIT tunnels and for more than net.ipv6.route.gc_thresh flows.
--- net/ipv6/sit.c | 2 -- 1 file changed, 2 deletions(-)
net/ipv6/sit.c +0 -2
@@ -1079,7 +1079,6 @@ static void ipip6_tunnel_bind_dev(structif (tdev && !netif_is_l3_master (tdev)) {int t_hlen = tunnel->hlen +sizeof (struct iphdr ); - dev->hard_header_len = tdev->hard_header_len +sizeof (struct iphdr ); dev->mtu = tdev->mtu - t_hlen;if (dev->mtu <IPV6_MIN_MTU ) dev->mtu =IPV6_MIN_MTU ;
@@ -1371,7 +1370,6 @@ static void ipip6_tunnel_setup(struct ne dev->destructor = ipip6_dev_free; dev->type =ARPHRD_SIT ; - dev->hard_header_len =LL_MAX_HEADER + t_hlen; dev->mtu =ETH_DATA_LEN - t_hlen; dev->flags =IFF_NOARP ;netif_keep_dst (dev);
Greg Kroah-Hartman
maintainerPATCH 43/64 net/af_iucv: fix null pointer dereference on shutdown
In reply to Greg Kroah-HartmanFrom: Ursula Braun <[email protected]>
[ Upstream commit 4031eeafa71eaf22ae40a15606a134ae86345daf ]
syzbot reported the following KASAN finding:
BUG: KASAN: nullptr-dereference in iucv_send_ctrl+0x390/0x3f0 net/iucv/af_iucv.c:385 Read of size 2 at addr 000000000000021e by task syz-executor907/519 CPU: 0 PID: 519 Comm: syz-executor907 Not tainted 5.9.0-syzkaller-07043-gbcf9877ad213 #0 Hardware name: IBM 3906 M04 701 (KVM/Linux) Call Trace: [<00000000c576af60>] unwind_start arch/s390/include/asm/unwind.h:65 [inline] [<00000000c576af60>] show_stack+0x180/0x228 arch/s390/kernel/dumpstack.c:135 [<00000000c9dcd1f8>] __dump_stack lib/dump_stack.c:77 [inline] [<00000000c9dcd1f8>] dump_stack+0x268/0x2f0 lib/dump_stack.c:118 [<00000000c5fed016>] print_address_description.constprop.0+0x5e/0x218 mm/kasan/report.c:383 [<00000000c5fec82a>] __kasan_report mm/kasan/report.c:517 [inline] [<00000000c5fec82a>] kasan_report+0x11a/0x168 mm/kasan/report.c:534 [<00000000c98b5b60>] iucv_send_ctrl+0x390/0x3f0 net/iucv/af_iucv.c:385 [<00000000c98b6262>] iucv_sock_shutdown+0x44a/0x4c0 net/iucv/af_iucv.c:1457 [<00000000c89d3a54>] __sys_shutdown+0x12c/0x1c8 net/socket.c:2204 [<00000000c89d3b70>] __do_sys_shutdown net/socket.c:2212 [inline] [<00000000c89d3b70>] __s390x_sys_shutdown+0x38/0x48 net/socket.c:2210 [<00000000c9e36eac>] system_call+0xe0/0x28c arch/s390/kernel/entry.S:415
There is nothing to shutdown if a connection has never been established. Besides that iucv->hs_dev is not yet initialized if a socket is in IUCV_OPEN state and iucv->path is not yet initialized if socket is in IUCV_BOUND state.
So, just skip the shutdown calls for a socket in these states.
--- net/iucv/af_iucv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/iucv/af_iucv.c +2 -1
@@ -1513,7 +1513,8 @@ static int iucv_sock_shutdown(struct socbreak ; } -if (how ==SEND_SHUTDOWN || how ==SHUTDOWN_MASK ) { +if ((how ==SEND_SHUTDOWN || how ==SHUTDOWN_MASK ) && + sk->sk_state ==IUCV_CONNECTED ) {if (iucv->transport ==AF_IUCV_TRANS_IUCV ) { txmsg.class =0 ; txmsg.tag =0 ;
Greg Kroah-Hartman
maintainerPATCH 44/64 net/x25: Fix null-ptr-deref in x25_connect
In reply to Greg Kroah-HartmanFrom: Martin Schiller <[email protected]>
[ Upstream commit 361182308766a265b6c521879b34302617a8c209 ]
This fixes a regression for blocking connects introduced by commit 4becb7ee5b3d ("net/x25: Fix x25_neigh refcnt leak when x25 disconnect").
The x25->neighbour is already set to "NULL" by x25_disconnect() now, while a blocking connect is waiting in x25_wait_for_connection_establishment(). Therefore x25->neighbour must not be accessed here again and x25->state is also already set to X25_STATE_0 by x25_disconnect().
--- net/x25/af_x25.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/x25/af_x25.c +1 -1
@@ -823,7 +823,7 @@ static int x25_connect(struct socket *so sock->state =SS_CONNECTED ; rc =0 ; out_put_neigh: -if (rc) { +if (rc && x25->neighbour) {read_lock_bh (&x25_list_lock);x25_neigh_put (x25->neighbour); x25->neighbour =NULL ;
Greg Kroah-Hartman
maintainerPATCH 45/64 net: Update window_clamp if SOCK_RCVBUF is set
In reply to Greg Kroah-HartmanFrom: Mao Wenan <[email protected]>
[ Upstream commit 909172a149749242990a6e64cb55d55460d4e417 ]
When net.ipv4.tcp_syncookies=1 and syn flood is happened, cookie_v4_check or cookie_v6_check tries to redo what tcp_v4_send_synack or tcp_v6_send_synack did, rsk_window_clamp will be changed if SOCK_RCVBUF is set, which will make rcv_wscale is different, the client still operates with initial window scale and can overshot granted window, the client use the initial scale but local server use new scale to advertise window value, and session work abnormally.
--- net/ipv4/syncookies.c | 9 +++++++-- net/ipv6/syncookies.c | 10 ++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-)
net/ipv4/syncookies.c +7 -2
@@ -307,7 +307,7 @@ struct sock *cookie_v4_check(struct sock__u32 cookie =ntohl (th->ack_seq) -1 ;struct sock *ret = sk;struct request_sock *req; -int mss; +int full_space, mss;struct rtable *rt;__u8 rcv_wscale;struct flowi4 fl4;
@@ -391,8 +391,13 @@ struct sock *cookie_v4_check(struct sock/* Try to redo what tcp_v4_send_synack did. */ req->rsk_window_clamp = tp->window_clamp ? :dst_metric (&rt->dst,RTAX_WINDOW ); +/* limit the window selection if the user enforce a smaller rx buffer */ + full_space =tcp_full_space (sk); +if (sk->sk_userlocks &SOCK_RCVBUF_LOCK && + (req->rsk_window_clamp > full_space || req->rsk_window_clamp ==0 )) + req->rsk_window_clamp = full_space; -tcp_select_initial_window (tcp_full_space (sk), req->mss, +tcp_select_initial_window (full_space, req->mss, &req->rsk_rcv_wnd, &req->rsk_window_clamp, ireq->wscale_ok, &rcv_wscale,dst_metric (&rt->dst,RTAX_INITRWND ));
net/ipv6/syncookies.c +8 -2
@@ -144,7 +144,7 @@ struct sock *cookie_v6_check(struct sock__u32 cookie =ntohl (th->ack_seq) -1 ;struct sock *ret = sk;struct request_sock *req; -int mss; +int full_space, mss;struct dst_entry *dst;__u8 rcv_wscale;
@@ -237,7 +237,13 @@ struct sock *cookie_v6_check(struct sock } req->rsk_window_clamp = tp->window_clamp ? :dst_metric (dst,RTAX_WINDOW ); -tcp_select_initial_window (tcp_full_space (sk), req->mss, +/* limit the window selection if the user enforce a smaller rx buffer */ + full_space =tcp_full_space (sk); +if (sk->sk_userlocks &SOCK_RCVBUF_LOCK && + (req->rsk_window_clamp > full_space || req->rsk_window_clamp ==0 )) + req->rsk_window_clamp = full_space; + +tcp_select_initial_window (full_space, req->mss, &req->rsk_rcv_wnd, &req->rsk_window_clamp, ireq->wscale_ok, &rcv_wscale,dst_metric (dst,RTAX_INITRWND ));
Greg Kroah-Hartman
maintainerPATCH 46/64 random32: make prandom_u32() output unpredictable
In reply to Greg Kroah-HartmanFrom: George Spelvin <[email protected]>
commit c51f8f88d705e06bd696d7510aff22b33eb8e638 upstream.
Non-cryptographic PRNGs may have great statistical properties, but are usually trivially predictable to someone who knows the algorithm, given a small sample of their output. An LFSR like prandom_u32() is particularly simple, even if the sample is widely scattered bits.
It turns out the network stack uses prandom_u32() for some things like random port numbers which it would prefer are *not* trivially predictable. Predictability led to a practical DNS spoofing attack. Oops.
This patch replaces the LFSR with a homebrew cryptographic PRNG based on the SipHash round function, which is in turn seeded with 128 bits of strong random key. (The authors of SipHash have *not* been consulted about this abuse of their algorithm.) Speed is prioritized over security; attacks are rare, while performance is always wanted.
Replacing all callers of prandom_u32() is the quick fix. Whether to reinstate a weaker PRNG for uses which can tolerate it is an open question.
Commit f227e3ec3b5c ("random32: update the net random state on interrupt and activity") was an earlier attempt at a solution. This patch replaces it.
[ willy: partial reversal of f227e3ec3b5c; moved SIPROUND definitions
to prandom.h for later use; merged George's prandom_seed() proposal; inlined siprand_u32(); replaced the net_rand_state[] array with 4 members to fix a build issue; cosmetic cleanups to make checkpatch happy; fixed RANDOM32_SELFTEST build ]
--- drivers/char/random.c | 2 include/linux/prandom.h | 36 +++ kernel/time/timer.c | 7 lib/random32.c | 463 +++++++++++++++++++++++++++++------------------- 4 files changed, 317 insertions(+), 191 deletions(-)
drivers/char/random.c +0 -2
@@ -678,7 +678,6 @@ retry: r->initialized =1 ; r->entropy_total =0 ;if (r == &nonblocking_pool) { -prandom_reseed_late ();process_random_ready_list ();wake_up_all (&urandom_init_wait);pr_notice ("random: %s pool is initialized\n" , r->name);
@@ -923,7 +922,6 @@ void add_interrupt_randomness(int irq, ifast_mix (fast_pool);add_interrupt_bench (cycles); -this_cpu_add (net_rand_state.s1, fast_pool->pool[cycles &3 ]);if ((fast_pool->count <64 ) && !time_after (now, fast_pool->last +HZ ))
include/linux/prandom.h +34 -2
@@ -16,12 +16,44 @@ void prandom_bytes(void *buf, size_t nbyvoid prandom_seed (u32 seed);void prandom_reseed_late (void ); +#if BITS_PER_LONG ==64 +/* +* The core SipHash round function. Each line can be executed in +* parallel given enough CPU resources. +*/ +#define PRND_SIPROUND (v0, v1, v2, v3) ( \ + v0 += v1, v1 = rol64(v1, 13), v2 += v3, v3 = rol64(v3, 16), \ + v1 ^= v0, v0 = rol64(v0, 32), v3 ^= v2, \ + v0 += v3, v3 = rol64(v3, 21), v2 += v1, v1 = rol64(v1, 17), \ + v3 ^= v0, v1 ^= v2, v2 = rol64(v2, 32) \ +) + +#define PRND_K0 (0x736f6d6570736575 ^ 0x6c7967656e657261) +#define PRND_K1 (0x646f72616e646f6d ^ 0x7465646279746573) + +#elif BITS_PER_LONG ==32 +/* +* On 32-bit machines, we use HSipHash, a reduced-width version of SipHash. +* This is weaker, but 32-bit machines are not used for high-traffic +* applications, so there is less output for an attacker to analyze. +*/ +#define PRND_SIPROUND (v0, v1, v2, v3) ( \ + v0 += v1, v1 = rol32(v1, 5), v2 += v3, v3 = rol32(v3, 8), \ + v1 ^= v0, v0 = rol32(v0, 16), v3 ^= v2, \ + v0 += v3, v3 = rol32(v3, 7), v2 += v1, v1 = rol32(v1, 13), \ + v3 ^= v0, v1 ^= v2, v2 = rol32(v2, 16) \ +) +#define PRND_K0 0x6c796765 +#define PRND_K1 0x74656462 + +#else +#error Unsupported BITS_PER_LONG +#endif +struct rnd_state {__u32 s1, s2, s3, s4; }; -DECLARE_PER_CPU(struct rnd_state, net_rand_state); -u32 prandom_u32_state (struct rnd_state *state);void prandom_bytes_state (struct rnd_state *state,void *buf,size_t nbytes);void prandom_seed_full_state (struct rnd_state __percpu *pcpu_state);
kernel/time/timer.c +0 -7
@@ -1432,13 +1432,6 @@ void update_process_times(int user_tick)#endif scheduler_tick ();run_posix_cpu_timers (p); - -/* The current CPU might make use of net randoms without receiving IRQs -* to renew them often enough. Let's update the net_rand_state from a -* non-constant value that's not affine to the number of calls to make -* sure it's updated when there's some activity (we don't care in idle). -*/ -this_cpu_add (net_rand_state.s1,rol32 (jiffies,24 ) + user_tick); }/*
lib/random32.c +283 -180
504 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 47/64 x86/speculation: Allow IBPB to be conditionally enabled on CPUs with always-on STIBP
In reply to Greg Kroah-HartmanFrom: Anand K Mistry <[email protected]>
commit 1978b3a53a74e3230cd46932b149c6e62e832e9a upstream.
On AMD CPUs which have the feature X86_FEATURE_AMD_STIBP_ALWAYS_ON, STIBP is set to on and
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED
At the same time, IBPB can be set to conditional.
However, this leads to the case where it's impossible to turn on IBPB for a process because in the PR_SPEC_DISABLE case in ib_prctl_set() the
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED
condition leads to a return before the task flag is set. Similarly, ib_prctl_get() will return PR_SPEC_DISABLE even though IBPB is set to conditional.
More generally, the following cases are possible:
1. STIBP = conditional && IBPB = on for spectre_v2_user=seccomp,ibpb
2. STIBP = on && IBPB = conditional for AMD CPUs with X86_FEATURE_AMD_STIBP_ALWAYS_ON
The first case functions correctly today, but only because spectre_v2_user_ibpb isn't updated to reflect the IBPB mode.
At a high level, this change does one thing. If either STIBP or IBPB is set to conditional, allow the prctl to change the task flag. Also, reflect that capability when querying the state. This isn't perfect since it doesn't take into account if only STIBP or IBPB is unconditionally on. But it allows the conditional feature to work as expected, without affecting the unconditional one.
[ bp: Massage commit message and comment; space out statements for
better readability. ]
--- arch/x86/kernel/cpu/bugs.c | 52 ++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 19 deletions(-)
arch/x86/kernel/cpu/bugs.c +33 -19
@@ -1223,6 +1223,14 @@ static int ssb_prctl_set(struct task_strreturn 0 ; } +static bool is_spec_ib_user_controlled (void ) +{ +return spectre_v2_user_ibpb ==SPECTRE_V2_USER_PRCTL || + spectre_v2_user_ibpb ==SPECTRE_V2_USER_SECCOMP || + spectre_v2_user_stibp ==SPECTRE_V2_USER_PRCTL || + spectre_v2_user_stibp ==SPECTRE_V2_USER_SECCOMP ; +} +static int ib_prctl_set (struct task_struct *task,unsigned long ctrl) {switch (ctrl) {
@@ -1230,17 +1238,26 @@ static int ib_prctl_set(struct task_struif (spectre_v2_user_ibpb ==SPECTRE_V2_USER_NONE && spectre_v2_user_stibp ==SPECTRE_V2_USER_NONE )return 0 ; -/* -* Indirect branch speculation is always disabled in strict -* mode. It can neither be enabled if it was force-disabled -* by a previous prctl call. +/* +* With strict mode for both IBPB and STIBP, the instruction +* code paths avoid checking this task flag and instead, +* unconditionally run the instruction. However, STIBP and IBPB +* are independent and either can be set to conditionally +* enabled regardless of the mode of the other. +* +* If either is set to conditional, allow the task flag to be +* updated, unless it was force-disabled by a previous prctl +* call. Currently, this is possible on an AMD CPU which has the +* feature X86_FEATURE_AMD_STIBP_ALWAYS_ON. In this case, if the +* kernel is booted with 'spectre_v2_user=seccomp', then +* spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP and +* spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED. */ -if (spectre_v2_user_ibpb ==SPECTRE_V2_USER_STRICT || - spectre_v2_user_stibp ==SPECTRE_V2_USER_STRICT || - spectre_v2_user_stibp ==SPECTRE_V2_USER_STRICT_PREFERRED || +if (!is_spec_ib_user_controlled () ||task_spec_ib_force_disable (task))return -EPERM ; +task_clear_spec_ib_disable (task);task_update_spec_tif (task);break ;
@@ -1253,10 +1270,10 @@ static int ib_prctl_set(struct task_struif (spectre_v2_user_ibpb ==SPECTRE_V2_USER_NONE && spectre_v2_user_stibp ==SPECTRE_V2_USER_NONE )return -EPERM ; -if (spectre_v2_user_ibpb ==SPECTRE_V2_USER_STRICT || - spectre_v2_user_stibp ==SPECTRE_V2_USER_STRICT || - spectre_v2_user_stibp ==SPECTRE_V2_USER_STRICT_PREFERRED ) + +if (!is_spec_ib_user_controlled ())return 0 ; +task_set_spec_ib_disable (task);if (ctrl ==PR_SPEC_FORCE_DISABLE )task_set_spec_ib_force_disable (task);
@@ -1319,20 +1336,17 @@ static int ib_prctl_get(struct task_struif (spectre_v2_user_ibpb ==SPECTRE_V2_USER_NONE && spectre_v2_user_stibp ==SPECTRE_V2_USER_NONE )return PR_SPEC_ENABLE ; -else if (spectre_v2_user_ibpb ==SPECTRE_V2_USER_STRICT || - spectre_v2_user_stibp ==SPECTRE_V2_USER_STRICT || - spectre_v2_user_stibp ==SPECTRE_V2_USER_STRICT_PREFERRED ) -return PR_SPEC_DISABLE ; -else if (spectre_v2_user_ibpb ==SPECTRE_V2_USER_PRCTL || - spectre_v2_user_ibpb ==SPECTRE_V2_USER_SECCOMP || - spectre_v2_user_stibp ==SPECTRE_V2_USER_PRCTL || - spectre_v2_user_stibp ==SPECTRE_V2_USER_SECCOMP ) { +else if (is_spec_ib_user_controlled ()) {if (task_spec_ib_force_disable (task))return PR_SPEC_PRCTL |PR_SPEC_FORCE_DISABLE ;if (task_spec_ib_disable (task))return PR_SPEC_PRCTL |PR_SPEC_DISABLE ;return PR_SPEC_PRCTL |PR_SPEC_ENABLE ; - }else + }else if (spectre_v2_user_ibpb ==SPECTRE_V2_USER_STRICT || + spectre_v2_user_stibp ==SPECTRE_V2_USER_STRICT || + spectre_v2_user_stibp ==SPECTRE_V2_USER_STRICT_PREFERRED ) +return PR_SPEC_DISABLE ; +else return PR_SPEC_NOT_AFFECTED ; }
Greg Kroah-Hartman
maintainerPATCH 48/64 xen/events: avoid removing an event channel while handling it
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit 073d0552ead5bfc7a3a9c01de590e924f11b5dd2 upstream.
Today it can happen that an event channel is being removed from the system while the event handling loop is active. This can lead to a race resulting in crashes or WARN() splats when trying to access the irq_info structure related to the event channel.
Fix this problem by using a rwlock taken as reader in the event handling loop and as writer when deallocating the irq_info structure.
As the observed problem was a NULL dereference in evtchn_from_irq() make this function more robust against races by testing the irq_info pointer to be not NULL before dereferencing it.
And finally make all accesses to evtchn_to_irq[row][col] atomic ones in order to avoid seeing partial updates of an array element in irq handling. Note that irq handling can be entered only for event channels which have been valid before, so any not populated row isn't a problem in this regard, as rows are only ever added and never removed.
This is XSA-331.
--- drivers/xen/events/events_base.c | 40 ++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-)
drivers/xen/events/events_base.c +35 -5
@@ -32,6 +32,7 @@#include <linux/slab.h> #include <linux/irqnr.h> #include <linux/pci.h> +#include <linux/spinlock.h> #ifdef CONFIG_X86 #include <asm/desc.h>
@@ -70,6 +71,23 @@ const struct evtchn_ops *evtchn_ops;*/ static DEFINE_MUTEX (irq_mapping_update_lock); +/* +* Lock protecting event handling loop against removing event channels. +* Adding of event channels is no issue as the associated IRQ becomes active +* only after everything is setup (before request_[threaded_]irq() the handler +* can't be entered for an event, as the event channel will be unmasked only +* then). +*/ +static DEFINE_RWLOCK (evtchn_rwlock); + +/* +* Lock hierarchy: +* +* irq_mapping_update_lock +* evtchn_rwlock +* IRQ-desc lock +*/ +static LIST_HEAD (xen_irq_list_head);/* IRQ <-> VIRQ mapping. */
@@ -104,7 +122,7 @@ static void clear_evtchn_to_irq_row(unsiunsigned col;for (col =0 ; col <EVTCHN_PER_ROW ; col++) - evtchn_to_irq[row][col] =-1 ; +WRITE_ONCE (evtchn_to_irq[row][col],-1 ); }static void clear_evtchn_to_irq_all (void )
@@ -141,7 +159,7 @@ static int set_evtchn_to_irq(unsigned evclear_evtchn_to_irq_row (row); } - evtchn_to_irq[row][col] = irq; +WRITE_ONCE (evtchn_to_irq[row][col], irq);return 0 ; }
@@ -151,7 +169,7 @@ int get_evtchn_to_irq(unsigned evtchn)return -1 ;if (evtchn_to_irq[EVTCHN_ROW (evtchn)] ==NULL )return -1 ; -return evtchn_to_irq[EVTCHN_ROW (evtchn)][EVTCHN_COL (evtchn)]; +return READ_ONCE (evtchn_to_irq[EVTCHN_ROW (evtchn)][EVTCHN_COL (evtchn)]); }/* Get info for IRQ */
@@ -260,10 +278,14 @@ static void xen_irq_info_cleanup(struct*/ unsigned int evtchn_from_irq (unsigned irq) { -if (unlikely (WARN (irq >= nr_irqs,"Invalid irq %d!\n" , irq))) +const struct irq_info *info =NULL ; + +if (likely (irq < nr_irqs)) + info =info_for_irq (irq); +if (!info)return 0 ; -return info_for_irq (irq)->evtchn; +return info->evtchn; }unsigned irq_from_evtchn (unsigned int evtchn)
@@ -447,16 +469,21 @@ static int __must_check xen_allocate_irqstatic void xen_free_irq (unsigned irq) {struct irq_info *info =info_for_irq (irq); +unsigned long flags;if (WARN_ON (!info))return ; +write_lock_irqsave (&evtchn_rwlock, flags); +list_del (&info->list);set_info_for_irq (irq,NULL );WARN_ON (info->refcnt >0 ); +write_unlock_irqrestore (&evtchn_rwlock, flags); +kfree (info);/* Legacy IRQ descriptors are managed by the arch. */
@@ -1241,6 +1268,8 @@ static void __xen_evtchn_do_upcall(void)int cpu =get_cpu ();unsigned count; +read_lock (&evtchn_rwlock); + do { vcpu_info->evtchn_upcall_pending = 0;
@@ -1256,6 +1285,7 @@ static void __xen_evtchn_do_upcall(void) }while (count !=1 || vcpu_info->evtchn_upcall_pending); out: +read_unlock (&evtchn_rwlock);put_cpu (); }
Greg Kroah-Hartman
maintainerPATCH 49/64 xen/events: add a proper barrier to 2-level uevent unmasking
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit 4d3fe31bd993ef504350989786858aefdb877daa upstream.
A follow-up patch will require certain write to happen before an event channel is unmasked.
While the memory barrier is not strictly necessary for all the callers, the main one will need it. In order to avoid an extra memory barrier when using fifo event channels, mandate evtchn_unmask() to provide write ordering.
The 2-level event handling unmask operation is missing an appropriate barrier, so add it. Fifo event channels are fine in this regard due to using sync_cmpxchg().
This is part of XSA-332.
--- drivers/xen/events/events_2l.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/xen/events/events_2l.c +2 -0
@@ -90,6 +90,8 @@ static void evtchn_2l_unmask(unsigned poBUG_ON (!irqs_disabled ()); +smp_wmb ();/* All writes before unmask must be visible. */ +if (unlikely ((cpu !=cpu_from_evtchn (port)))) do_hypercall =1 ;else {
Greg Kroah-Hartman
maintainerPATCH 50/64 xen/events: fix race in evtchn_fifo_unmask()
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit f01337197419b7e8a492e83089552b77d3b5fb90 upstream.
Unmasking a fifo event channel can result in unmasking it twice, once directly in the kernel and once via a hypercall in case the event was pending.
Fix that by doing the local unmask only if the event is not pending.
This is part of XSA-332.
--- drivers/xen/events/events_fifo.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
drivers/xen/events/events_fifo.c +9 -4
@@ -227,19 +227,25 @@ static bool evtchn_fifo_is_masked(unsignreturn sync_test_bit (EVTCHN_FIFO_BIT (MASKED , word),BM (word)); }/* -* Clear MASKED, spinning if BUSY is set. +* Clear MASKED if not PENDING, spinning if BUSY is set. +* Return true if mask was cleared. */ -static void clear_masked (volatile event_word_t *word) +static bool clear_masked_cond (volatile event_word_t *word) {event_word_t new, old, w; w = *word;do { +if (w & (1 <<EVTCHN_FIFO_PENDING )) +return false; + old = w & ~(1 <<EVTCHN_FIFO_BUSY ); new = old & ~(1 <<EVTCHN_FIFO_MASKED ); w =sync_cmpxchg (word, old, new); }while (w != old); + +return true; }static void evtchn_fifo_unmask (unsigned port)
@@ -248,8 +254,7 @@ static void evtchn_fifo_unmask(unsignedBUG_ON (!irqs_disabled ()); -clear_masked (word); -if (evtchn_fifo_is_pending (port)) { +if (!clear_masked_cond (word)) {struct evtchn_unmask unmask = { .port = port }; (void )HYPERVISOR_event_channel_op (EVTCHNOP_unmask, &unmask); }
Greg Kroah-Hartman
maintainerPATCH 51/64 xen/events: add a new "late EOI" evtchn framework
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit 54c9de89895e0a36047fcc4ae754ea5b8655fb9d upstream.
In order to avoid tight event channel related IRQ loops add a new framework of "late EOI" handling: the IRQ the event channel is bound to will be masked until the event has been handled and the related driver is capable to handle another event. The driver is responsible for unmasking the event channel via the new function xen_irq_lateeoi().
This is similar to binding an event channel to a threaded IRQ, but without having to structure the driver accordingly.
In order to support a future special handling in case a rogue guest is sending lots of unsolicited events, add a flag to xen_irq_lateeoi() which can be set by the caller to indicate the event was a spurious one.
This is part of XSA-332.
--- drivers/xen/events/events_base.c | 151 ++++++++++++++++++++++++++++++++++----- include/xen/events.h | 29 ++++++- 2 files changed, 159 insertions(+), 21 deletions(-)
drivers/xen/events/events_base.c +134 -17
@@ -112,6 +112,7 @@ static bool (*pirq_needs_eoi)(unsigned istatic struct irq_info *legacy_info_ptrs[NR_IRQS_LEGACY ];static struct irq_chip xen_dynamic_chip; +static struct irq_chip xen_lateeoi_chip;static struct irq_chip xen_percpu_chip;static struct irq_chip xen_pirq_chip;static void enable_dynirq (struct irq_data *data);
@@ -404,6 +405,33 @@ void notify_remote_via_irq(int irq) }EXPORT_SYMBOL_GPL (notify_remote_via_irq); +static void xen_irq_lateeoi_locked (struct irq_info *info) +{ +evtchn_port_t evtchn; + + evtchn = info->evtchn; +if (!VALID_EVTCHN (evtchn)) +return ; + +unmask_evtchn (evtchn); +} + +void xen_irq_lateeoi (unsigned int irq,unsigned int eoi_flags) +{ +struct irq_info *info; +unsigned long flags; + +read_lock_irqsave (&evtchn_rwlock, flags); + + info =info_for_irq (irq); + +if (info) +xen_irq_lateeoi_locked (info); + +read_unlock_irqrestore (&evtchn_rwlock, flags); +} +EXPORT_SYMBOL_GPL (xen_irq_lateeoi); +static void xen_irq_init (unsigned irq) {struct irq_info *info;
@@ -875,7 +903,7 @@ int xen_pirq_from_irq(unsigned irq) }EXPORT_SYMBOL_GPL (xen_pirq_from_irq); -int bind_evtchn_to_irq (unsigned int evtchn) +static int bind_evtchn_to_irq_chip (evtchn_port_t evtchn,struct irq_chip *chip) {int irq;int ret;
@@ -892,7 +920,7 @@ int bind_evtchn_to_irq(unsigned int evtcif (irq <0 ) goto out; -irq_set_chip_and_handler_name (irq, &xen_dynamic_chip, +irq_set_chip_and_handler_name (irq, chip, handle_edge_irq,"event" ); ret =xen_irq_info_evtchn_setup (irq, evtchn);
@@ -913,8 +941,19 @@ out:return irq; } + +int bind_evtchn_to_irq (evtchn_port_t evtchn) +{ +return bind_evtchn_to_irq_chip (evtchn, &xen_dynamic_chip); +}EXPORT_SYMBOL_GPL (bind_evtchn_to_irq); +int bind_evtchn_to_irq_lateeoi (evtchn_port_t evtchn) +{ +return bind_evtchn_to_irq_chip (evtchn, &xen_lateeoi_chip); +} +EXPORT_SYMBOL_GPL (bind_evtchn_to_irq_lateeoi); +static int bind_ipi_to_irq (unsigned int ipi,unsigned int cpu) {struct evtchn_bind_ipi bind_ipi;
@@ -956,8 +995,9 @@ static int bind_ipi_to_irq(unsigned intreturn irq; } -int bind_interdomain_evtchn_to_irq (unsigned int remote_domain, -unsigned int remote_port) +static int bind_interdomain_evtchn_to_irq_chip (unsigned int remote_domain, +evtchn_port_t remote_port, +struct irq_chip *chip) {struct evtchn_bind_interdomain bind_interdomain;int err;
@@ -968,10 +1008,26 @@ int bind_interdomain_evtchn_to_irq(unsig err =HYPERVISOR_event_channel_op (EVTCHNOP_bind_interdomain, &bind_interdomain); -return err ? :bind_evtchn_to_irq (bind_interdomain.local_port); +return err ? :bind_evtchn_to_irq_chip (bind_interdomain.local_port, + chip); +} + +int bind_interdomain_evtchn_to_irq (unsigned int remote_domain, +evtchn_port_t remote_port) +{ +return bind_interdomain_evtchn_to_irq_chip (remote_domain, remote_port, + &xen_dynamic_chip); }EXPORT_SYMBOL_GPL (bind_interdomain_evtchn_to_irq); +int bind_interdomain_evtchn_to_irq_lateeoi (unsigned int remote_domain, +evtchn_port_t remote_port) +{ +return bind_interdomain_evtchn_to_irq_chip (remote_domain, remote_port, + &xen_lateeoi_chip); +} +EXPORT_SYMBOL_GPL (bind_interdomain_evtchn_to_irq_lateeoi); +static int find_virq (unsigned int virq,unsigned int cpu) {struct evtchn_status status;
@@ -1067,14 +1123,15 @@ static void unbind_from_irq(unsigned intmutex_unlock (&irq_mapping_update_lock); } -int bind_evtchn_to_irqhandler (unsigned int evtchn, -irq_handler_t handler, -unsigned long irqflags, -const char *devname,void *dev_id) +static int bind_evtchn_to_irqhandler_chip (evtchn_port_t evtchn, +irq_handler_t handler, +unsigned long irqflags, +const char *devname,void *dev_id, +struct irq_chip *chip) {int irq, retval; - irq =bind_evtchn_to_irq (evtchn); + irq =bind_evtchn_to_irq_chip (evtchn, chip);if (irq <0 )return irq; retval =request_irq (irq, handler, irqflags, devname, dev_id);
@@ -1085,18 +1142,38 @@ int bind_evtchn_to_irqhandler(unsigned ireturn irq; } + +int bind_evtchn_to_irqhandler (evtchn_port_t evtchn, +irq_handler_t handler, +unsigned long irqflags, +const char *devname,void *dev_id) +{ +return bind_evtchn_to_irqhandler_chip (evtchn, handler, irqflags, + devname, dev_id, + &xen_dynamic_chip); +}EXPORT_SYMBOL_GPL (bind_evtchn_to_irqhandler); -int bind_interdomain_evtchn_to_irqhandler (unsigned int remote_domain, -unsigned int remote_port, -irq_handler_t handler, -unsigned long irqflags, -const char *devname, -void *dev_id) +int bind_evtchn_to_irqhandler_lateeoi (evtchn_port_t evtchn, +irq_handler_t handler, +unsigned long irqflags, +const char *devname,void *dev_id) +{ +return bind_evtchn_to_irqhandler_chip (evtchn, handler, irqflags, + devname, dev_id, + &xen_lateeoi_chip); +} +EXPORT_SYMBOL_GPL (bind_evtchn_to_irqhandler_lateeoi); + +static int bind_interdomain_evtchn_to_irqhandler_chip ( +unsigned int remote_domain,evtchn_port_t remote_port, +irq_handler_t handler,unsigned long irqflags, +const char *devname,void *dev_id,struct irq_chip *chip) {int irq, retval; - irq =bind_interdomain_evtchn_to_irq (remote_domain, remote_port); + irq =bind_interdomain_evtchn_to_irq_chip (remote_domain, remote_port, + chip);if (irq <0 )return irq;
@@ -1108,8 +1185,33 @@ int bind_interdomain_evtchn_to_irqhandlereturn irq; } + +int bind_interdomain_evtchn_to_irqhandler (unsigned int remote_domain, +evtchn_port_t remote_port, +irq_handler_t handler, +unsigned long irqflags, +const char *devname, +void *dev_id) +{ +return bind_interdomain_evtchn_to_irqhandler_chip (remote_domain, + remote_port, handler, irqflags, devname, + dev_id, &xen_dynamic_chip); +}EXPORT_SYMBOL_GPL (bind_interdomain_evtchn_to_irqhandler); +int bind_interdomain_evtchn_to_irqhandler_lateeoi (unsigned int remote_domain, +evtchn_port_t remote_port, +irq_handler_t handler, +unsigned long irqflags, +const char *devname, +void *dev_id) +{ +return bind_interdomain_evtchn_to_irqhandler_chip (remote_domain, + remote_port, handler, irqflags, devname, + dev_id, &xen_lateeoi_chip); +} +EXPORT_SYMBOL_GPL (bind_interdomain_evtchn_to_irqhandler_lateeoi); +int bind_virq_to_irqhandler (unsigned int virq,unsigned int cpu,irq_handler_t handler,unsigned long irqflags,const char *devname,void *dev_id)
@@ -1639,6 +1741,21 @@ static struct irq_chip xen_dynamic_chip .irq_mask_ack = mask_ack_dynirq, .irq_set_affinity = set_affinity_irq, + .irq_retrigger = retrigger_dynirq, +}; + +static struct irq_chip xen_lateeoi_chip__read_mostly = { +/* The chip name needs to contain "xen-dyn" for irqbalance to work. */ + .name ="xen-dyn-lateeoi" , + + .irq_disable = disable_dynirq, + .irq_mask = disable_dynirq, + .irq_unmask = enable_dynirq, + + .irq_ack = mask_ack_dynirq, + .irq_mask_ack = mask_ack_dynirq, + + .irq_set_affinity = set_affinity_irq, .irq_retrigger = retrigger_dynirq, };
include/xen/events.h +25 -4
@@ -12,11 +12,16 @@unsigned xen_evtchn_nr_channels (void ); -int bind_evtchn_to_irq (unsigned int evtchn); -int bind_evtchn_to_irqhandler (unsigned int evtchn, +int bind_evtchn_to_irq (evtchn_port_t evtchn); +int bind_evtchn_to_irq_lateeoi (evtchn_port_t evtchn); +int bind_evtchn_to_irqhandler (evtchn_port_t evtchn,irq_handler_t handler,unsigned long irqflags,const char *devname,void *dev_id); +int bind_evtchn_to_irqhandler_lateeoi (evtchn_port_t evtchn, +irq_handler_t handler, +unsigned long irqflags,const char *devname, +void *dev_id);int bind_virq_to_irq (unsigned int virq,unsigned int cpu,bool percpu); int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu, irq_handler_t handler,
@@ -29,13 +34,21 @@ int bind_ipi_to_irqhandler(enum ipi_vectconst char *devname, void *dev_id);int bind_interdomain_evtchn_to_irq (unsigned int remote_domain, -unsigned int remote_port); +evtchn_port_t remote_port); +int bind_interdomain_evtchn_to_irq_lateeoi (unsigned int remote_domain, +evtchn_port_t remote_port);int bind_interdomain_evtchn_to_irqhandler (unsigned int remote_domain, -unsigned int remote_port, +evtchn_port_t remote_port,irq_handler_t handler,unsigned long irqflags,const char *devname,void *dev_id); +int bind_interdomain_evtchn_to_irqhandler_lateeoi (unsigned int remote_domain, +evtchn_port_t remote_port, +irq_handler_t handler, +unsigned long irqflags, +const char *devname, +void *dev_id);/* * Common unbind function for all event sources. Takes IRQ to unbind from.
@@ -44,6 +57,14 @@ int bind_interdomain_evtchn_to_irqhandle*/ void unbind_from_irqhandler (unsigned int irq,void *dev_id); +/* +* Send late EOI for an IRQ bound to an event channel via one of the *_lateeoi +* functions above. +*/ +void xen_irq_lateeoi (unsigned int irq,unsigned int eoi_flags); +/* Signal an event was spurious, i.e. there was no action resulting from it. */ +#define XEN_EOI_FLAG_SPURIOUS 0x00000001 +#define XEN_IRQ_PRIORITY_MAX EVTCHN_FIFO_PRIORITY_MAX#define XEN_IRQ_PRIORITY_DEFAULT EVTCHN_FIFO_PRIORITY_DEFAULT#define XEN_IRQ_PRIORITY_MIN EVTCHN_FIFO_PRIORITY_MIN
Greg Kroah-Hartman
maintainerPATCH 52/64 xen/blkback: use lateeoi irq binding
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit 01263a1fabe30b4d542f34c7e2364a22587ddaf2 upstream.
In order to reduce the chance for the system becoming unresponsive due to event storms triggered by a misbehaving blkfront use the lateeoi irq binding for blkback and unmask the event channel only after processing all pending requests.
As the thread processing requests is used to do purging work in regular intervals an EOI may be sent only after having received an event. If there was no pending I/O request flag the EOI as spurious.
This is part of XSA-332.
--- drivers/block/xen-blkback/blkback.c | 22 +++++++++++++++++----- drivers/block/xen-blkback/xenbus.c | 5 ++--- 2 files changed, 19 insertions(+), 8 deletions(-)
drivers/block/xen-blkback/blkback.c +17 -5
@@ -173,7 +173,7 @@ static inline void shrink_free_pagepool(#define vaddr (page) ((unsigned long)pfn_to_kaddr(page_to_pfn(page))) -static int do_block_io_op (struct xen_blkif *blkif); +static int do_block_io_op (struct xen_blkif *blkif,unsigned int *eoi_flags);static int dispatch_rw_block_io (struct xen_blkif *blkif,struct blkif_request *req,struct pending_req *pending_req);
@@ -594,6 +594,8 @@ int xen_blkif_schedule(void *arg)struct xen_vbd *vbd = &blkif->vbd;unsigned long timeout;int ret; +bool do_eoi; +unsigned int eoi_flags =XEN_EOI_FLAG_SPURIOUS ;while (!kthread_should_stop ()) {if (try_to_freeze ())
@@ -617,16 +619,23 @@ int xen_blkif_schedule(void *arg)if (timeout ==0 ) goto purge_gnt_list; + do_eoi = blkif->waiting_reqs; + blkif->waiting_reqs =0 ;smp_mb ();/* clear flag *before* checking for work */ - ret =do_block_io_op (blkif); + ret =do_block_io_op (blkif, &eoi_flags);if (ret >0 ) blkif->waiting_reqs =1 ;if (ret == -EACCES )wait_event_interruptible (blkif->shutdown_wq,kthread_should_stop ()); +if (do_eoi && !blkif->waiting_reqs) { +xen_irq_lateeoi (blkif->irq, eoi_flags); + eoi_flags |=XEN_EOI_FLAG_SPURIOUS ; + } + purge_gnt_list:if (blkif->vbd.feature_gnt_persistent &&time_after (jiffies, blkif->next_lru)) {
@@ -1094,7 +1103,7 @@ static void end_block_io_op(struct bio ** and transmute it to the block API to hand it over to the proper block disk. */ static int -__do_block_io_op (struct xen_blkif *blkif) +__do_block_io_op (struct xen_blkif *blkif,unsigned int *eoi_flags) {union blkif_back_rings *blk_rings = &blkif->blk_rings;struct blkif_request req;
@@ -1117,6 +1126,9 @@ __do_block_io_op(struct xen_blkif *blkifif (RING_REQUEST_CONS_OVERFLOW (&blk_rings->common, rc))break ; +/* We've seen a request, so clear spurious eoi flag. */ + *eoi_flags &= ~XEN_EOI_FLAG_SPURIOUS ; +if (kthread_should_stop ()) { more_to_do =1 ;break ;
@@ -1175,13 +1187,13 @@ done: }static int -do_block_io_op (struct xen_blkif *blkif) +do_block_io_op (struct xen_blkif *blkif,unsigned int *eoi_flags) {union blkif_back_rings *blk_rings = &blkif->blk_rings;int more_to_do; do { - more_to_do = __do_block_io_op(blkif); + more_to_do = __do_block_io_op(blkif, eoi_flags); if (more_to_do) break;
drivers/block/xen-blkback/xenbus.c +2 -3
@@ -200,9 +200,8 @@ static int xen_blkif_map(struct xen_blkiBUG (); } - err =bind_interdomain_evtchn_to_irqhandler (blkif->domid, evtchn, - xen_blkif_be_int,0 , -"blkif-backend" , blkif); + err =bind_interdomain_evtchn_to_irqhandler_lateeoi (blkif->domid, + evtchn, xen_blkif_be_int,0 ,"blkif-backend" , blkif);if (err <0 ) {xenbus_unmap_ring_vfree (blkif->be->dev, blkif->blk_ring); blkif->blk_rings.common.sring =NULL ;
Greg Kroah-Hartman
maintainerPATCH 53/64 xen/netback: use lateeoi irq binding
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit 23025393dbeb3b8b3b60ebfa724cdae384992e27 upstream.
In order to reduce the chance for the system becoming unresponsive due to event storms triggered by a misbehaving netfront use the lateeoi irq binding for netback and unmask the event channel only just before going to sleep waiting for new events.
Make sure not to issue an EOI when none is pending by introducing an eoi_pending element to struct xenvif_queue.
When no request has been consumed set the spurious flag when sending the EOI for an interrupt.
This is part of XSA-332.
--- drivers/net/xen-netback/common.h | 39 +++++++++++++++++++++++ drivers/net/xen-netback/interface.c | 59 +++++++++++++++++++++++++++++++----- drivers/net/xen-netback/netback.c | 17 +++++++--- 3 files changed, 103 insertions(+), 12 deletions(-)
drivers/net/xen-netback/common.h +39 -0
@@ -137,6 +137,20 @@ struct xenvif_queue { /* Per-queue datachar name[QUEUE_NAME_SIZE ];/* DEVNAME-qN */ struct xenvif *vif;/* Parent VIF */ +/* +* TX/RX common EOI handling. +* When feature-split-event-channels = 0, interrupt handler sets +* NETBK_COMMON_EOI, otherwise NETBK_RX_EOI and NETBK_TX_EOI are set +* by the RX and TX interrupt handlers. +* RX and TX handler threads will issue an EOI when either +* NETBK_COMMON_EOI or their specific bits (NETBK_RX_EOI or +* NETBK_TX_EOI) are set and they will reset those bits. +*/ +atomic_t eoi_pending; +#define NETBK_RX_EOI 0x01 +#define NETBK_TX_EOI 0x02 +#define NETBK_COMMON_EOI 0x04 +/* Use NAPI for guest TX */ struct napi_struct napi;/* When feature-split-event-channels = 0, tx_irq = rx_irq. */
@@ -317,6 +331,7 @@ void xenvif_kick_thread(struct xenvif_quint xenvif_dealloc_kthread (void *data); +bool xenvif_have_rx_work (struct xenvif_queue *queue,bool test_kthread);void xenvif_rx_queue_tail (struct xenvif_queue *queue,struct sk_buff *skb);void xenvif_carrier_on (struct xenvif *vif);
@@ -353,4 +368,28 @@ void xenvif_skb_zerocopy_complete(structbool xenvif_mcast_match (struct xenvif *vif,const u8 *addr);void xenvif_mcast_addr_list_free (struct xenvif *vif); +#include <linux/atomic.h> + +static inline int xenvif_atomic_fetch_or (int i,atomic_t *v) +{ +int c, old; + + c = v->counter; +while ((old =cmpxchg (&v->counter, c, c | i)) != c) + c = old; + +return c; +} + +static inline int xenvif_atomic_fetch_andnot (int i,atomic_t *v) +{ +int c, old; + + c = v->counter; +while ((old =cmpxchg (&v->counter, c, c & ~i)) != c) + c = old; + +return c; +} +#endif /* __XEN_NETBACK__COMMON_H__ */
drivers/net/xen-netback/interface.c +51 -8
103 lines not on this page · raw message
drivers/net/xen-netback/netback.c +13 -4
@@ -670,6 +670,10 @@ void xenvif_napi_schedule_or_enable_evenif (more_to_do)napi_schedule (&queue->napi); +else if (xenvif_atomic_fetch_andnot (NETBK_TX_EOI |NETBK_COMMON_EOI , + &queue->eoi_pending) & + (NETBK_TX_EOI |NETBK_COMMON_EOI )) +xen_irq_lateeoi (queue->tx_irq,0 ); }static void tx_add_credit (struct xenvif_queue *queue)
@@ -2010,14 +2014,14 @@ static bool xenvif_rx_queue_ready(structreturn queue->stalled && prod - cons >=1 ; } -static bool xenvif_have_rx_work (struct xenvif_queue *queue) +bool xenvif_have_rx_work (struct xenvif_queue *queue,bool test_kthread) {return (!skb_queue_empty (&queue->rx_queue) &&xenvif_rx_ring_slots_available (queue)) || (queue->vif->stall_timeout && (xenvif_rx_queue_stalled (queue) ||xenvif_rx_queue_ready (queue))) - ||kthread_should_stop () + || (test_kthread &&kthread_should_stop ()) || queue->vif->disabled; }
@@ -2048,15 +2052,20 @@ static void xenvif_wait_for_rx_work(stru {DEFINE_WAIT (wait); -if (xenvif_have_rx_work (queue)) +if (xenvif_have_rx_work (queue, true))return ;for (;;) {long ret;prepare_to_wait (&queue->wq, &wait,TASK_INTERRUPTIBLE ); -if (xenvif_have_rx_work (queue)) +if (xenvif_have_rx_work (queue, true))break ; +if (xenvif_atomic_fetch_andnot (NETBK_RX_EOI |NETBK_COMMON_EOI , + &queue->eoi_pending) & + (NETBK_RX_EOI |NETBK_COMMON_EOI )) +xen_irq_lateeoi (queue->rx_irq,0 ); + ret =schedule_timeout (xenvif_rx_queue_timeout (queue));if (!ret)break ;
Greg Kroah-Hartman
maintainerPATCH 54/64 xen/scsiback: use lateeoi irq binding
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit 86991b6e7ea6c613b7692f65106076943449b6b7 upstream.
In order to reduce the chance for the system becoming unresponsive due to event storms triggered by a misbehaving scsifront use the lateeoi irq binding for scsiback and unmask the event channel only just before leaving the event handling function.
In case of a ring protocol error don't issue an EOI in order to avoid the possibility to use that for producing an event storm. This at once will result in no further call of scsiback_irq_fn(), so the ring_error struct member can be dropped and scsiback_do_cmd_fn() can signal the protocol error via a negative return value.
This is part of XSA-332.
--- drivers/xen/xen-scsiback.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-)
drivers/xen/xen-scsiback.c +13 -10
@@ -91,7 +91,6 @@ struct vscsibk_info {unsigned int irq;struct vscsiif_back_ring ring; -int ring_error;spinlock_t ring_lock;atomic_t nr_unreplied_reqs;
@@ -698,7 +697,8 @@ static int prepare_pending_reqs(struct vreturn 0 ; } -static int scsiback_do_cmd_fn (struct vscsibk_info *info) +static int scsiback_do_cmd_fn (struct vscsibk_info *info, +unsigned int *eoi_flags) {struct vscsiif_back_ring *ring = &info->ring;struct vscsiif_request ring_req;
@@ -715,11 +715,12 @@ static int scsiback_do_cmd_fn(struct vsc rc = ring->rsp_prod_pvt;pr_warn ("Dom%d provided bogus ring requests (%#x - %#x = %u). Halting ring processing\n" , info->domid, rp, rc, rp - rc); - info->ring_error =1 ; -return 0 ; +return -EINVAL ; }while ((rc != rp)) { + *eoi_flags &= ~XEN_EOI_FLAG_SPURIOUS ; +if (RING_REQUEST_CONS_OVERFLOW (ring, rc))break ; pending_req =kmem_cache_alloc (scsiback_cachep,GFP_KERNEL );
@@ -782,13 +783,16 @@ static int scsiback_do_cmd_fn(struct vscstatic irqreturn_t scsiback_irq_fn (int irq,void *dev_id) {struct vscsibk_info *info = dev_id; +int rc; +unsigned int eoi_flags =XEN_EOI_FLAG_SPURIOUS ; -if (info->ring_error) -return IRQ_HANDLED ; - -while (scsiback_do_cmd_fn (info)) +while ((rc =scsiback_do_cmd_fn (info, &eoi_flags)) >0 )cond_resched (); +/* In case of a ring error we keep the event channel masked. */ +if (!rc) +xen_irq_lateeoi (irq, eoi_flags); +return IRQ_HANDLED ; }
@@ -809,7 +813,7 @@ static int scsiback_init_sring(struct vs sring = (struct vscsiif_sring *)area;BACK_RING_INIT (&info->ring, sring,PAGE_SIZE ); - err =bind_interdomain_evtchn_to_irq (info->domid, evtchn); + err =bind_interdomain_evtchn_to_irq_lateeoi (info->domid, evtchn);if (err <0 ) goto unmap_page;
@@ -1210,7 +1214,6 @@ static int scsiback_probe(struct xenbus_ info->domid = dev->otherend_id;spin_lock_init (&info->ring_lock); - info->ring_error =0 ;atomic_set (&info->nr_unreplied_reqs,0 );init_waitqueue_head (&info->waiting_to_free); info->dev = dev;
Greg Kroah-Hartman
maintainerPATCH 55/64 xen/pciback: use lateeoi irq binding
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit c2711441bc961b37bba0615dd7135857d189035f upstream.
In order to reduce the chance for the system becoming unresponsive due to event storms triggered by a misbehaving pcifront use the lateeoi irq binding for pciback and unmask the event channel only just before leaving the event handling function.
Restructure the handling to support that scheme. Basically an event can come in for two reasons: either a normal request for a pciback action, which is handled in a worker, or in case the guest has finished an AER request which was requested by pciback.
When an AER request is issued to the guest and a normal pciback action is currently active issue an EOI early in order to be able to receive another event when the AER request has been finished by the guest.
Let the worker processing the normal requests run until no further request is pending, instead of starting a new worker ion that case. Issue the EOI only just before leaving the worker.
This scheme allows to drop calling the generic function xen_pcibk_test_and_schedule_op() after processing of any request as the handling of both request types is now separated more cleanly.
This is part of XSA-332.
--- drivers/xen/xen-pciback/pci_stub.c | 14 ++++----- drivers/xen/xen-pciback/pciback.h | 12 +++++++- drivers/xen/xen-pciback/pciback_ops.c | 48 ++++++++++++++++++++++++++-------- drivers/xen/xen-pciback/xenbus.c | 2 - 4 files changed, 56 insertions(+), 20 deletions(-)
drivers/xen/xen-pciback/pci_stub.c +7 -7
@@ -681,10 +681,17 @@ static pci_ers_result_t common_process(swmb ();notify_remote_via_irq (pdev->evtchn_irq); +/* Enable IRQ to signal "request done". */ +xen_pcibk_lateeoi (pdev,0 ); + ret =wait_event_timeout (xen_pcibk_aer_wait_queue, !(test_bit (_XEN_PCIB_active, (unsigned long *) &sh_info->flags)),300 *HZ ); +/* Enable IRQ for pcifront request if not already active. */ +if (!test_bit (_PDEVF_op_active, &pdev->flags)) +xen_pcibk_lateeoi (pdev,0 ); +if (!ret) {if (test_bit (_XEN_PCIB_active, (unsigned long *)&sh_info->flags)) {
@@ -698,13 +705,6 @@ static pci_ers_result_t common_process(s }clear_bit (_PCIB_op_pending, (unsigned long *)&pdev->flags); -if (test_bit (_XEN_PCIF_active, - (unsigned long *)&sh_info->flags)) { -dev_dbg (&psdev->dev->dev, -"schedule pci_conf service in " DRV_NAME "\n" ); -xen_pcibk_test_and_schedule_op (psdev->pdev); - } - res = (pci_ers_result_t )aer_op->err;return res; }
drivers/xen/xen-pciback/pciback.h +10 -2
@@ -13,6 +13,7 @@#include <linux/spinlock.h> #include <linux/workqueue.h> #include <linux/atomic.h> +#include <xen/events.h> #include <xen/interface/io/pciif.h> #define DRV_NAME "xen-pciback"
@@ -26,6 +27,8 @@ struct pci_dev_entry {#define PDEVF_op_active (1<<(_PDEVF_op_active))#define _PCIB_op_pending (1)#define PCIB_op_pending (1<<(_PCIB_op_pending)) +#define _EOI_pending (2) +#define EOI_pending (1<<(_EOI_pending))struct xen_pcibk_device {void *pci_dev_data;
@@ -182,12 +185,17 @@ static inline void xen_pcibk_release_devirqreturn_t xen_pcibk_handle_event (int irq,void *dev_id);void xen_pcibk_do_op (struct work_struct *data); +static inline void xen_pcibk_lateeoi (struct xen_pcibk_device *pdev, +unsigned int eoi_flag) +{ +if (test_and_clear_bit (_EOI_pending, &pdev->flags)) +xen_irq_lateeoi (pdev->evtchn_irq, eoi_flag); +} +int xen_pcibk_xenbus_register (void );void xen_pcibk_xenbus_unregister (void );extern int verbose_request; - -void xen_pcibk_test_and_schedule_op (struct xen_pcibk_device *pdev);#endif /* Handles shared IRQs that can to device domain and control domain. */
drivers/xen/xen-pciback/pciback_ops.c +38 -10
90 lines not on this page · raw message
drivers/xen/xen-pciback/xenbus.c +1 -1
@@ -124,7 +124,7 @@ static int xen_pcibk_do_attach(struct xe pdev->sh_info = vaddr; - err =bind_interdomain_evtchn_to_irqhandler ( + err =bind_interdomain_evtchn_to_irqhandler_lateeoi ( pdev->xdev->otherend_id, remote_evtchn, xen_pcibk_handle_event,0 ,DRV_NAME , pdev);if (err <0 ) {
Greg Kroah-Hartman
maintainerPATCH 56/64 xen/events: switch user event channels to lateeoi model
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit c44b849cee8c3ac587da3b0980e01f77500d158c upstream.
Instead of disabling the irq when an event is received and enabling it again when handled by the user process use the lateeoi model.
This is part of XSA-332.
--- drivers/xen/evtchn.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
drivers/xen/evtchn.c +3 -4
@@ -173,7 +173,6 @@ static irqreturn_t evtchn_interrupt(int"Interrupt for port %d, but apparently not enabled; per-user %p\n" , evtchn->port, u); -disable_irq_nosync (irq); evtchn->enabled = false;spin_lock (&u->ring_prod_lock);
@@ -299,7 +298,7 @@ static ssize_t evtchn_write(struct file evtchn =find_evtchn (u, port);if (evtchn && !evtchn->enabled) { evtchn->enabled = true; -enable_irq (irq_from_evtchn (port)); +xen_irq_lateeoi (irq_from_evtchn (port),0 ); } }
@@ -399,8 +398,8 @@ static int evtchn_bind_to_user(struct peif (rc <0 ) goto err; - rc =bind_evtchn_to_irqhandler (port, evtchn_interrupt,0 , - u->name, evtchn); + rc =bind_evtchn_to_irqhandler_lateeoi (port, evtchn_interrupt,0 , + u->name, evtchn);if (rc <0 ) goto err;
Greg Kroah-Hartman
maintainerPATCH 57/64 xen/events: use a common cpu hotplug hook for event channels
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit 7beb290caa2adb0a399e735a1e175db9aae0523a upstream.
Today only fifo event channels have a cpu hotplug callback. In order to prepare for more percpu (de)init work move that callback into events_base.c and add percpu_init() and percpu_deinit() hooks to struct evtchn_ops.
This is part of XSA-332.
--- drivers/xen/events/events_base.c | 47 +++++++++++++++++++++++++++ drivers/xen/events/events_fifo.c | 59 ++++++++++++++--------------------- drivers/xen/events/events_internal.h | 3 + 3 files changed, 74 insertions(+), 35 deletions(-)
drivers/xen/events/events_base.c +47 -0
@@ -33,6 +33,7 @@#include <linux/irqnr.h> #include <linux/pci.h> #include <linux/spinlock.h> +#include <linux/cpu.h> #ifdef CONFIG_X86 #include <asm/desc.h>
@@ -1832,6 +1833,50 @@ void xen_callback_vector(void) {}static bool fifo_events = true;module_param (fifo_events, bool,0 ); +static int xen_evtchn_cpu_prepare (unsigned int cpu) +{ +int ret =0 ; + +if (evtchn_ops->percpu_init) + ret = evtchn_ops->percpu_init (cpu); + +return ret; +} + +static int xen_evtchn_cpu_dead (unsigned int cpu) +{ +int ret =0 ; + +if (evtchn_ops->percpu_deinit) + ret = evtchn_ops->percpu_deinit (cpu); + +return ret; +} + +static int evtchn_cpu_notification (struct notifier_block *self, +unsigned long action,void *hcpu) +{ +int cpu = (long )hcpu; +int ret =0 ; + +switch (action) { +case CPU_UP_PREPARE : + ret =xen_evtchn_cpu_prepare (cpu); +break ; +case CPU_DEAD : + ret =xen_evtchn_cpu_dead (cpu); +break ; +default : +break ; + } + +return ret <0 ?NOTIFY_BAD :NOTIFY_OK ; +} + +static struct notifier_block evtchn_cpu_notifier = { + .notifier_call = evtchn_cpu_notification, +}; +void __init xen_init_IRQ (void ) {int ret = -EINVAL ;
@@ -1841,6 +1886,8 @@ void __init xen_init_IRQ(void)if (ret <0 )xen_evtchn_2l_init (); +register_cpu_notifier (&evtchn_cpu_notifier); + evtchn_to_irq =kcalloc (EVTCHN_ROW (xen_evtchn_max_channels ()),sizeof (*evtchn_to_irq),GFP_KERNEL );BUG_ON (!evtchn_to_irq);
drivers/xen/events/events_fifo.c +24 -35
81 lines not on this page · raw message
drivers/xen/events/events_internal.h +3 -0
@@ -71,6 +71,9 @@ struct evtchn_ops {void (*handle_events)(unsigned cpu);void (*resume)(void ); + +int (*percpu_init)(unsigned int cpu); +int (*percpu_deinit)(unsigned int cpu); };extern const struct evtchn_ops *evtchn_ops;
Greg Kroah-Hartman
maintainerPATCH 58/64 xen/events: defer eoi in case of excessive number of events
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit e99502f76271d6bc4e374fe368c50c67a1fd3070 upstream.
In case rogue guests are sending events at high frequency it might happen that xen_evtchn_do_upcall() won't stop processing events in dom0. As this is done in irq handling a crash might be the result.
In order to avoid that, delay further inter-domain events after some time in xen_evtchn_do_upcall() by forcing eoi processing into a worker on the same cpu, thus inhibiting new events coming in.
The time after which eoi processing is to be delayed is configurable via a new module parameter "event_loop_timeout" which specifies the maximum event loop time in jiffies (default: 2, the value was chosen after some tests showing that a value of 2 was the lowest with an only slight drop of dom0 network throughput while multiple guests performed an event storm).
How long eoi processing will be delayed can be specified via another parameter "event_eoi_delay" (again in jiffies, default 10, again the value was chosen after testing with different delay values).
This is part of XSA-332.
--- Documentation/kernel-parameters.txt | 8 + drivers/xen/events/events_2l.c | 7 - drivers/xen/events/events_base.c | 189 ++++++++++++++++++++++++++++++++++- drivers/xen/events/events_fifo.c | 30 ++--- drivers/xen/events/events_internal.h | 14 ++ 5 files changed, 216 insertions(+), 32 deletions(-)
Documentation/kernel-parameters.txt +8 -0
@@ -4488,6 +4488,14 @@ bytes respectively. Such letter suffixes Disables the PV optimizations forcing the HVM guest to run as generic HVM guest with no PV drivers. + xen.event_eoi_delay= [XEN] + How long to delay EOI handling in case of event + storms (jiffies). Default is 10. + + xen.event_loop_timeout= [XEN] + After which time (jiffies) the event handling loop + should start to delay EOI handling. Default is 2. + xirc2ps_cs= [NET,PCMCIA] Format: <irq>,<irq_mask>,<io>,<full_duplex>,<do_sound>,<lockup_hack>[,<irq2>[,<irq3>[,<irq4>]]]
drivers/xen/events/events_2l.c +2 -5
@@ -160,7 +160,7 @@ static inline xen_ulong_t active_evtchns* a bitset of words which contain pending event bits. The second * level is a bitset of pending events themselves. */ -static void evtchn_2l_handle_events (unsigned cpu) +static void evtchn_2l_handle_events (unsigned cpu,struct evtchn_loop_ctrl *ctrl) {int irq;xen_ulong_t pending_words;
@@ -241,10 +241,7 @@ static void evtchn_2l_handle_events(unsi/* Process port. */ port = (word_idx *BITS_PER_EVTCHN_WORD ) + bit_idx; - irq =get_evtchn_to_irq (port); - -if (irq !=-1 ) -generic_handle_irq (irq); +handle_irq_for_port (port, ctrl); bit_idx = (bit_idx +1 ) %BITS_PER_EVTCHN_WORD ;
drivers/xen/events/events_base.c +184 -5
289 lines not on this page · raw message
drivers/xen/events/events_fifo.c +11 -19
@@ -275,19 +275,9 @@ static uint32_t clear_linked(volatile evreturn w &EVTCHN_FIFO_LINK_MASK ; } -static void handle_irq_for_port (unsigned port) -{ -int irq; - - irq =get_evtchn_to_irq (port); -if (irq !=-1 ) -generic_handle_irq (irq); -} - -static void consume_one_event (unsigned cpu, +static void consume_one_event (unsigned cpu,struct evtchn_loop_ctrl *ctrl,struct evtchn_fifo_control_block *control_block, -unsigned priority,unsigned long *ready, -bool drop) +unsigned priority,unsigned long *ready) {struct evtchn_fifo_queue *q = &per_cpu (cpu_queue, cpu);uint32_t head;
@@ -320,16 +310,17 @@ static void consume_one_event(unsigned cclear_bit (priority, ready);if (evtchn_fifo_is_pending (port) && !evtchn_fifo_is_masked (port)) { -if (unlikely (drop)) +if (unlikely (!ctrl))pr_warn ("Dropping pending event for port %u\n" , port);else -handle_irq_for_port (port); +handle_irq_for_port (port, ctrl); } q->head[priority] = head; } -static void __evtchn_fifo_handle_events (unsigned cpu,bool drop) +static void __evtchn_fifo_handle_events (unsigned cpu, +struct evtchn_loop_ctrl *ctrl) {struct evtchn_fifo_control_block *control_block;unsigned long ready;
@@ -341,14 +332,15 @@ static void __evtchn_fifo_handle_events(while (ready) { q =find_first_bit (&ready,EVTCHN_FIFO_MAX_QUEUES ); -consume_one_event (cpu, control_block, q, &ready, drop); +consume_one_event (cpu, ctrl, control_block, q, &ready); ready |=xchg (&control_block->ready,0 ); } } -static void evtchn_fifo_handle_events (unsigned cpu) +static void evtchn_fifo_handle_events (unsigned cpu, +struct evtchn_loop_ctrl *ctrl) { -__evtchn_fifo_handle_events (cpu, false); +__evtchn_fifo_handle_events (cpu, ctrl); }static void evtchn_fifo_resume (void )
@@ -417,7 +409,7 @@ static int evtchn_fifo_percpu_init(unsigstatic int evtchn_fifo_percpu_deinit (unsigned int cpu) { -__evtchn_fifo_handle_events (cpu, true); +__evtchn_fifo_handle_events (cpu,NULL );return 0 ; }
drivers/xen/events/events_internal.h +11 -3
@@ -32,11 +32,15 @@ enum xen_irq_type {*/ struct irq_info {struct list_head list; +struct list_head eoi_list;int refcnt;enum xen_irq_type type;/* type */ unsigned irq;unsigned int evtchn;/* event channel */ unsigned short cpu;/* cpu bound */ +unsigned short eoi_cpu;/* EOI must happen on this cpu */ +unsigned int irq_epoch;/* If eoi_cpu valid: irq_epoch of event */ +u64 eoi_time;/* Time in jiffies when to EOI. */ union {unsigned short virq;
@@ -55,6 +59,8 @@ struct irq_info {#define PIRQ_SHAREABLE (1 << 1)#define PIRQ_MSI_GROUP (1 << 2) +struct evtchn_loop_ctrl ; +struct evtchn_ops {unsigned (*max_channels)(void );unsigned (*nr_channels)(void );
@@ -69,7 +75,7 @@ struct evtchn_ops {void (*mask)(unsigned port);void (*unmask)(unsigned port); -void (*handle_events)(unsigned cpu); +void (*handle_events)(unsigned cpu,struct evtchn_loop_ctrl *ctrl);void (*resume)(void );int (*percpu_init)(unsigned int cpu);
@@ -80,6 +86,7 @@ extern const struct evtchn_ops *evtchn_oextern int **evtchn_to_irq;int get_evtchn_to_irq (unsigned int evtchn); +void handle_irq_for_port (evtchn_port_t port,struct evtchn_loop_ctrl *ctrl);struct irq_info *info_for_irq (unsigned irq);unsigned cpu_from_irq (unsigned irq);
@@ -137,9 +144,10 @@ static inline void unmask_evtchn(unsignereturn evtchn_ops->unmask (port); } -static inline void xen_evtchn_handle_events (unsigned cpu) +static inline void xen_evtchn_handle_events (unsigned cpu, +struct evtchn_loop_ctrl *ctrl) { -return evtchn_ops->handle_events (cpu); +return evtchn_ops->handle_events (cpu, ctrl); }static inline void xen_evtchn_resume (void )
Greg Kroah-Hartman
maintainerPATCH 59/64 xen/events: block rogue events for some time
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit 5f7f77400ab5b357b5fdb7122c3442239672186c upstream.
In order to avoid high dom0 load due to rogue guests sending events at high frequency, block those events in case there was no action needed in dom0 to handle the events.
This is done by adding a per-event counter, which set to zero in case an EOI without the XEN_EOI_FLAG_SPURIOUS is received from a backend driver, and incremented when this flag has been set. In case the counter is 2 or higher delay the EOI by 1 << (cnt - 2) jiffies, but not more than 1 second.
In order not to waste memory shorten the per-event refcnt to two bytes (it should normally never exceed a value of 2). Add an overflow check to evtchn_get() to make sure the 2 bytes really won't overflow.
This is part of XSA-332.
--- drivers/xen/events/events_base.c | 27 ++++++++++++++++++++++----- drivers/xen/events/events_internal.h | 3 ++- 2 files changed, 24 insertions(+), 6 deletions(-)
drivers/xen/events/events_base.c +22 -5
@@ -468,17 +468,34 @@ static void lateeoi_list_add(struct irq_spin_unlock_irqrestore (&eoi->eoi_list_lock, flags); } -static void xen_irq_lateeoi_locked (struct irq_info *info) +static void xen_irq_lateeoi_locked (struct irq_info *info,bool spurious) {evtchn_port_t evtchn;unsigned int cpu; +unsigned int delay =0 ; evtchn = info->evtchn;if (!VALID_EVTCHN (evtchn) || !list_empty (&info->eoi_list))return ; +if (spurious) { +if ((1 << info->spurious_cnt) < (HZ <<2 )) + info->spurious_cnt++; +if (info->spurious_cnt >1 ) { + delay =1 << (info->spurious_cnt -2 ); +if (delay >HZ ) + delay =HZ ; +if (!info->eoi_time) + info->eoi_cpu =smp_processor_id (); + info->eoi_time =get_jiffies_64 () + delay; + } + }else { + info->spurious_cnt =0 ; + } + cpu = info->eoi_cpu; -if (info->eoi_time && info->irq_epoch ==per_cpu (irq_epoch, cpu)) { +if (info->eoi_time && + (info->irq_epoch ==per_cpu (irq_epoch, cpu) || delay)) {lateeoi_list_add (info);return ; }
@@ -515,7 +532,7 @@ static void xen_irq_lateeoi_worker(struc info->eoi_time =0 ; -xen_irq_lateeoi_locked (info); +xen_irq_lateeoi_locked (info, false); }if (info)
@@ -544,7 +561,7 @@ void xen_irq_lateeoi(unsigned int irq, u info =info_for_irq (irq);if (info) -xen_irq_lateeoi_locked (info); +xen_irq_lateeoi_locked (info, eoi_flags &XEN_EOI_FLAG_SPURIOUS );read_unlock_irqrestore (&evtchn_rwlock, flags); }
@@ -1447,7 +1464,7 @@ int evtchn_get(unsigned int evtchn) goto done; err = -EINVAL ; -if (info->refcnt <=0 ) +if (info->refcnt <=0 || info->refcnt ==SHRT_MAX ) goto done; info->refcnt++;
drivers/xen/events/events_internal.h +2 -1
@@ -33,7 +33,8 @@ enum xen_irq_type {struct irq_info {struct list_head list;struct list_head eoi_list; -int refcnt; +short refcnt; +short spurious_cnt;enum xen_irq_type type;/* type */ unsigned irq;unsigned int evtchn;/* event channel */
Greg Kroah-Hartman
maintainerPATCH 60/64 perf/core: Fix race in the perf_mmap_close() function
In reply to Greg Kroah-HartmanFrom: Jiri Olsa <[email protected]>
commit f91072ed1b7283b13ca57fcfbece5a3b92726143 upstream.
There's a possible race in perf_mmap_close() when checking ring buffer's mmap_count refcount value. The problem is that the mmap_count check is not atomic because we call atomic_dec() and atomic_read() separately.
perf_mmap_close:
...
atomic_dec(&rb->mmap_count);
...
if (atomic_read(&rb->mmap_count))
goto out_put; <ring buffer detach>
free_uid
out_put:
ring_buffer_put(rb); /* could be last */
The race can happen when we have two (or more) events sharing same ring buffer and they go through atomic_dec() and then they both see 0 as refcount value later in atomic_read(). Then both will go on and execute code which is meant to be run just once.
The code that detaches ring buffer is probably fine to be executed more than once, but the problem is in calling free_uid(), which will later on demonstrate in related crashes and refcount warnings, like:
refcount_t: addition on 0; use-after-free.
...
RIP: 0010:refcount_warn_saturate+0x6d/0xf ... Call Trace: prepare_creds+0x190/0x1e0 copy_creds+0x35/0x172 copy_process+0x471/0x1a80 _do_fork+0x83/0x3a0 __do_sys_wait4+0x83/0x90 __do_sys_clone+0x85/0xa0 do_syscall_64+0x5b/0x1e0 entry_SYSCALL_64_after_hwframe+0x44/0xa9
Using atomic decrease and check instead of separated calls.
--- kernel/events/core.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
kernel/events/core.c +4 -3
@@ -4664,11 +4664,11 @@ static void perf_mmap_open(struct vm_arestatic void perf_mmap_close (struct vm_area_struct *vma) {struct perf_event *event = vma->vm_file->private_data; -struct ring_buffer *rb =ring_buffer_get (event);struct user_struct *mmap_user = rb->mmap_user;int mmap_locked = rb->mmap_locked;unsigned long size =perf_data_size (rb); +bool detach_rest = false;if (event->pmu->event_unmapped) event->pmu->event_unmapped (event);
@@ -4687,7 +4687,8 @@ static void perf_mmap_close(struct vm_armutex_unlock (&event->mmap_mutex); } -atomic_dec (&rb->mmap_count); +if (atomic_dec_and_test (&rb->mmap_count)) + detach_rest = true;if (!atomic_dec_and_mutex_lock (&event->mmap_count, &event->mmap_mutex)) goto out_put;
@@ -4696,7 +4697,7 @@ static void perf_mmap_close(struct vm_armutex_unlock (&event->mmap_mutex);/* If there's still other mmap()s of this buffer, we're done. */ -if (atomic_read (&rb->mmap_count)) +if (!detach_rest) goto out_put;/*
Greg Kroah-Hartman
maintainerPATCH 61/64 Revert "kernel/reboot.c: convert simple_strtoul to kstrtoint"
In reply to Greg Kroah-HartmanFrom: Matteo Croce <[email protected]>
commit 8b92c4ff4423aa9900cf838d3294fcade4dbda35 upstream.
Patch series "fix parsing of reboot= cmdline", v3.
The parsing of the reboot= cmdline has two major errors:
- a missing bound check can crash the system on reboot
- parsing of the cpu number only works if specified last
Fix both.
This patch (of 2):
This reverts commit 616feab753972b97.
kstrtoint() and simple_strtoul() have a subtle difference which makes them non interchangeable: if a non digit character is found amid the parsing, the former will return an error, while the latter will just stop parsing, e.g. simple_strtoul("123xyx") = 123.
The kernel cmdline reboot= argument allows to specify the CPU used for rebooting, with the syntax s#### among the other flags, e.g. "reboot=warm,s31,force", so if this flag is not the last given, it's silently ignored as well as the subsequent ones.
--- kernel/reboot.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-)
kernel/reboot.c +7 -14
@@ -512,22 +512,15 @@ static int __init reboot_setup(char *strbreak ;case 's' : - { -int rc; - -if (isdigit (*(str+1 ))) { - rc =kstrtoint (str+1 ,0 , &reboot_cpu); -if (rc) -return rc; - }else if (str[1 ] =='m' && str[2 ] =='p' && -isdigit (*(str+3 ))) { - rc =kstrtoint (str+3 ,0 , &reboot_cpu); -if (rc) -return rc; - }else +if (isdigit (*(str+1 ))) + reboot_cpu =simple_strtoul (str+1 ,NULL ,0 ); +else if (str[1 ] =='m' && str[2 ] =='p' && +isdigit (*(str+3 ))) + reboot_cpu =simple_strtoul (str+3 ,NULL ,0 ); +else reboot_mode =REBOOT_SOFT ;break ; - } +case 'g' : reboot_mode =REBOOT_GPIO ;break ;
Greg Kroah-Hartman
maintainerPATCH 62/64 reboot: fix overflow parsing reboot cpu number
In reply to Greg Kroah-HartmanFrom: Matteo Croce <[email protected]>
commit df5b0ab3e08a156701b537809914b339b0daa526 upstream.
Limit the CPU number to num_possible_cpus(), because setting it to a value lower than INT_MAX but higher than NR_CPUS produces the following error on reboot and shutdown:
BUG: unable to handle page fault for address: ffffffff90ab1bb0
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 1c09067 P4D 1c09067 PUD 1c0a063 PMD 0
Oops: 0000 [#1] SMP
CPU: 1 PID: 1 Comm: systemd-shutdow Not tainted 5.9.0-rc8-kvm #110
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-2.fc32 04/01/2014
RIP: 0010:migrate_to_reboot_cpu+0xe/0x60
Code: ea ea 00 48 89 fa 48 c7 c7 30 57 f1 81 e9 fa ef ff ff 66 2e 0f 1f 84 00 00 00 00 00 53 8b 1d d5 ea ea 00 e8 14 33 fe ff 89 da <48> 0f a3 15 ea fc bd 00 48 89 d0 73 29 89 c2 c1 e8 06 65 48 8b 3c
RSP: 0018:ffffc90000013e08 EFLAGS: 00010246
RAX: ffff88801f0a0000 RBX: 0000000077359400 RCX: 0000000000000000
RDX: 0000000077359400 RSI: 0000000000000002 RDI: ffffffff81c199e0
RBP: ffffffff81c1e3c0 R08: ffff88801f41f000 R09: ffffffff81c1e348
R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000
R13: 00007f32bedf8830 R14: 00000000fee1dead R15: 0000000000000000
FS: 00007f32bedf8980(0000) GS:ffff88801f480000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: ffffffff90ab1bb0 CR3: 000000001d057000 CR4: 00000000000006a0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
__do_sys_reboot.cold+0x34/0x5b
do_syscall_64+0x2d/0x40--- kernel/reboot.c | 7 +++++++ 1 file changed, 7 insertions(+)
kernel/reboot.c +7 -0
@@ -519,6 +519,13 @@ static int __init reboot_setup(char *str reboot_cpu =simple_strtoul (str+3 ,NULL ,0 ); else reboot_mode =REBOOT_SOFT ; +if (reboot_cpu >=num_possible_cpus ()) { +pr_err ("Ignoring the CPU number in reboot= option. " +"CPU %d exceeds possible cpu number %d\n" , + reboot_cpu,num_possible_cpus ()); + reboot_cpu =0 ; +break ; + }break ;case 'g' :
Greg Kroah-Hartman
maintainerPATCH 63/64 ext4: fix leaking sysfs kobject after failed mount
In reply to Greg Kroah-HartmanFrom: Eric Biggers <[email protected]>
commit cb8d53d2c97369029cc638c9274ac7be0a316c75 upstream.
ext4_unregister_sysfs() only deletes the kobject. The reference to it needs to be put separately, like ext4_put_super() does.
This addresses the syzbot report
"memory leak in kobject_set_name_vargs (3)"
(https://syzkaller.appspot.com/bug?extid=9f864abad79fae7c17e1).
--- fs/ext4/super.c | 1 + 1 file changed, 1 insertion(+)
fs/ext4/super.c +1 -0
@@ -4168,6 +4168,7 @@ cantfind_ext4:#ifdef CONFIG_QUOTA failed_mount8:ext4_unregister_sysfs (sb); +kobject_put (&sbi->s_kobj);#endif failed_mount7:ext4_unregister_li_request (sb);
Greg Kroah-Hartman
maintainerPATCH 64/64 Convert trailing spaces and periods in path components
In reply to Greg Kroah-HartmanFrom: Boris Protopopov <[email protected]>
commit 57c176074057531b249cf522d90c22313fa74b0b upstream.
When converting trailing spaces and periods in paths, do so for every component of the path, not just the last component. If the conversion is not done for every path component, then subsequent operations in directories with trailing spaces or periods (e.g. create(), mkdir()) will fail with ENOENT. This is because on the server, the directory will have a special symbol in its name, and the client needs to provide the same.
--- fs/cifs/cifs_unicode.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
fs/cifs/cifs_unicode.c +7 -1
@@ -493,7 +493,13 @@ cifsConvertToUTF16(__le16 *target, constelse if (map_chars ==SFM_MAP_UNI_RSVD ) {bool end_of_string; -if (i == srclen -1 ) +/** +* Remap spaces and periods found at the end of every +* component of the path. The special cases of '.' and +* '..' do not need to be dealt with explicitly because +* they are addressed in namei.c:link_path_walk(). +**/ +if ((i == srclen -1 ) || (source[i+1 ] =='\\' )) end_of_string = true;else end_of_string = false;
Hi!
Quoted 4 lines
This is the start of the stable review cycle for the 4.4.244 release. There are 64 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
CIP testing did not find any problems here:
https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/tree/linux-4.4.y
Best regards,
Pavel
Signature · 2 lines
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 4.4.244 release. There are 64 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 19 Nov 2020 12:20:51 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.4.244-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-4.4.y
and the diffstat can be found below.thanks,
greg k-h
All tests passing for Tegra ...
Test results for stable-v4.4:
6 builds: 6 pass, 0 fail
12 boots: 12 pass, 0 fail
25 tests: 25 pass, 0 failLinux version: 4.4.244-rc1-g5c64a4febafe
Boards tested: tegra124-jetson-tk1, tegra20-ventana,
tegra30-cardhu-a04
Jon
Quoted 10 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 4.4.244 release. There are 64 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 19 Nov 2020 12:20:51 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.4.244-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-4.4.y
and the diffstat can be found below.thanks,
greg k-h
Results from Linaro’s test farm.
No regressions on arm64, arm, x86_64, and i386.
Summary
------------------------------------------------------------------------
kernel: 4.4.244-rc1
git repo: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git
git branch: linux-4.4.y
git commit: 5c64a4febafe0af1834cf497df8985d917a94b05
git describe: v4.4.243-65-g5c64a4febafe
Test details: https://qa-reports.linaro.org/lkft/linux-stable-rc-linux-4.4.y/build/v4.4.243-65-g5c64a4febafe
No regressions (compared to build v4.4.243)
No fixes (compared to build v4.4.243)
Ran 32841 total tests in the following environments and test suites.
Environments
--------------
- i386
- juno-r2 - arm64
- juno-r2-compat
- juno-r2-kasan
- qemu-arm64-clang
- qemu-arm64-kasan
- qemu-x86_64-clang
- qemu-x86_64-kasan
- qemu_arm
- qemu_arm64
- qemu_arm64-compat
- qemu_i386
- qemu_x86_64
- qemu_x86_64-compat
- x15 - arm
- x86_64
- x86-kasan
Test Suites
-----------
* build
* libhugetlbfs
* linux-log-parser
* ltp-cap_bounds-tests
* ltp-commands-tests
* ltp-containers-tests
* ltp-controllers-tests
* ltp-cpuhotplug-tests
* ltp-crypto-tests
* ltp-cve-tests
* ltp-dio-tests
* ltp-fcntl-locktests-tests
* ltp-filecaps-tests
* ltp-fs-tests
* ltp-fs_bind-tests
* ltp-fs_perms_simple-tests
* ltp-fsx-tests
* ltp-hugetlb-tests
* ltp-io-tests
* ltp-ipc-tests
* ltp-math-tests
* ltp-mm-tests
* ltp-nptl-tests
* ltp-open-posix-tests
* ltp-pty-tests
* ltp-sched-tests
* ltp-securebits-tests
* ltp-syscalls-tests
* ltp-tracing-tests
* network-basic-tests
* perf
* v4l2-compliance
* kvm-unit-tests
* install-android-platform-tools-r2600
Summary
------------------------------------------------------------------------
kernel: 4.4.244-rc1
git repo: https://git.linaro.org/lkft/arm64-stable-rc.git
git branch: 4.4.244-rc1-hikey-20201117-859
git commit: cdeaa8f4dfeb6e5920b76b6ee2d57b77b2810576
git describe: 4.4.244-rc1-hikey-20201117-859
Test details: https://qa-reports.linaro.org/lkft/linaro-hikey-stable-rc-4.4-oe/build/4.4.244-rc1-hikey-20201117-859
No regressions (compared to build 4.4.244-rc1-hikey-20201114-857)
No fixes (compared to build 4.4.244-rc1-hikey-20201114-857)
Ran 1760 total tests in the following environments and test suites.
Environments
--------------
- hi6220-hikey - arm64
Test Suites
-----------
* build
* install-android-platform-tools-r2600
* libhugetlbfs
* linux-log-parser
* ltp-cap_bounds-tests
* ltp-commands-tests
* ltp-containers-tests
* ltp-cpuhotplug-tests
* ltp-cve-tests
* ltp-dio-tests
* ltp-fcntl-locktests-tests
* ltp-filecaps-tests
* ltp-fs-tests
* ltp-fs_bind-tests
* ltp-fs_perms_simple-tests
* ltp-fsx-tests
* ltp-hugetlb-tests
* ltp-io-tests
* ltp-ipc-tests
* ltp-math-tests
* ltp-mm-tests
* ltp-nptl-tests
* ltp-pty-tests
* ltp-sched-tests
* ltp-securebits-tests
* ltp-syscalls-tests
* perf
* spectre-meltdown-checker-test
* v4l2-compliance
Signature · 2 lines
Linaro LKFT https://lkft.linaro.org
Quoted 8 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 4.4.244 release. There are 64 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 19 Nov 2020 12:20:51 +0000. Anything received after that time might be too late.
Build results:
total: 165 pass: 165 fail: 0 Qemu test results: total: 328 pass: 328 fail: 0
Guenter