This is the start of the stable review cycle for the 5.3.14 release. There are 95 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 Fri, 29 Nov 2019 20:18:09 +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/v5.x/stable-review/patch-5.3.14-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.3.y and the diffstat can be found below.
thanks,
greg k-h
------------- Pseudo-Shortlog of commits:
Greg Kroah-Hartman gregkh@linuxfoundation.org Linux 5.3.14-rc1
Michael Ellerman mpe@ellerman.id.au KVM: PPC: Book3S HV: Flush link stack on guest exit to host kernel
Michael Ellerman mpe@ellerman.id.au powerpc/book3s64: Fix link stack flush on context switch
Christopher M. Riedl cmr@informatik.wtf powerpc/64s: support nospectre_v2 cmdline option
Bernd Porr mail@berndporr.me.uk staging: comedi: usbduxfast: usbduxfast_ai_cmdtest rounding error
Aleksander Morgado aleksander@aleksander.es USB: serial: option: add support for Foxconn T77W968 LTE modules
Aleksander Morgado aleksander@aleksander.es USB: serial: option: add support for DW5821e with eSIM support
Johan Hovold johan@kernel.org USB: serial: mos7840: fix remote wakeup
Johan Hovold johan@kernel.org USB: serial: mos7720: fix remote wakeup
Pavel Löbl pavel@loebl.cz USB: serial: mos7840: add USB ID to support Moxa UPort 2210
Oliver Neukum oneukum@suse.com appledisplay: fix error handling in the scheduled work
Oliver Neukum oneukum@suse.com USB: chaoskey: fix error case of a timeout
Greg Kroah-Hartman gregkh@linuxfoundation.org usb-serial: cp201x: support Mark-10 digital force gauge
Suwan Kim suwan.kim027@gmail.com usbip: Fix uninitialized symbol 'nents' in stub_recv_cmd_submit()
Hewenliang hewenliang4@huawei.com usbip: tools: fix fd leakage in the function of read_attr_usbip_status
Oliver Neukum oneukum@suse.com USBIP: add config dependency for SGL_ALLOC
Alexander Potapenko glider@google.com mm/slub.c: init_on_free=1 should wipe freelist ptr for bulk allocations
A Sun as1033x@comcast.net media: mceusb: fix out of bounds read in MCE receiver buffer
Sean Young sean@mess.org media: imon: invalid dereference in imon_touch_event
Vito Caputo vcaputo@pengaru.com media: cxusb: detect cxusb_ctrl_msg error in query
Oliver Neukum oneukum@suse.com media: b2c2-flexcop-usb: add sanity checking
Laurent Pinchart laurent.pinchart@ideasonboard.com media: uvcvideo: Fix error path in control parsing failure
Kai Shen shenkai8@huawei.com cpufreq: Add NULL checks to show() and store() methods of cpufreq
Alan Stern stern@rowland.harvard.edu media: usbvision: Fix races among open, close, and disconnect
Alan Stern stern@rowland.harvard.edu media: usbvision: Fix invalid accesses after device disconnect
Alexander Popov alex.popov@linux.com media: vivid: Fix wrong locking that causes race conditions on streaming stop
Vandana BN bnvandana@gmail.com media: vivid: Set vid_cap_streaming and vid_out_streaming to true
Jouni Hogander jouni.hogander@unikie.com net-sysfs: Fix reference count leak in rx|netdev_queue_add_kobject
Oliver Neukum oneukum@suse.com nfc: port100: handle command failure cleanly
Takashi Iwai tiwai@suse.de ALSA: usb-audio: Fix NULL dereference at parsing BADD
Yang Tao yang.tao172@zte.com.cn futex: Prevent robust futex exit race
Andy Lutomirski luto@kernel.org x86/entry/32: Fix FIXUP_ESPFIX_STACK with user CR3
Ingo Molnar mingo@kernel.org x86/pti/32: Calculate the various PTI cpu_entry_area sizes correctly, make the CPU_ENTRY_AREA_PAGES assert precise
Andy Lutomirski luto@kernel.org selftests/x86/sigreturn/32: Invalidate DS and ES when abusing the kernel
Andy Lutomirski luto@kernel.org selftests/x86/mov_ss_trap: Fix the SYSENTER test
Peter Zijlstra peterz@infradead.org x86/entry/32: Fix NMI vs ESPFIX
Andy Lutomirski luto@kernel.org x86/entry/32: Unwind the ESPFIX stack earlier on exception entry
Andy Lutomirski luto@kernel.org x86/entry/32: Move FIXUP_FRAME after pushing %fs in SAVE_ALL
Andy Lutomirski luto@kernel.org x86/entry/32: Use %ss segment where required
Peter Zijlstra peterz@infradead.org x86/entry/32: Fix IRET exception
Thomas Gleixner tglx@linutronix.de x86/cpu_entry_area: Add guard page for entry stack on 32bit
Thomas Gleixner tglx@linutronix.de x86/pti/32: Size initial_page_table correctly
Andy Lutomirski luto@kernel.org x86/doublefault/32: Fix stack canaries in the double fault handler
Jan Beulich jbeulich@suse.com x86/xen/32: Simplify ring check in xen_iret_crit_fixup()
Jan Beulich jbeulich@suse.com x86/xen/32: Make xen_iret_crit_fixup() independent of frame layout
Jan Beulich jbeulich@suse.com x86/stackframe/32: Repair 32-bit Xen PV
Adi Suresh adisuresh@google.com gve: fix dma sync bug where not all pages synced
Navid Emamdoost navid.emamdoost@gmail.com nbd: prevent memory leak
Waiman Long longman@redhat.com x86/speculation: Fix redundant MDS mitigation message
Waiman Long longman@redhat.com x86/speculation: Fix incorrect MDS/TAA mitigation status
Alexander Kapshuk alexander.kapshuk@gmail.com x86/insn: Fix awk regexp warnings
Chester Lin clin@suse.com ARM: 8904/1: skip nomap memblocks while finding the lowmem/highmem boundary
Geert Uytterhoeven geert+renesas@glider.be mdio_bus: Fix init if CONFIG_RESET_CONTROLLER=n
John Pittman jpittman@redhat.com md/raid10: prevent access of uninitialized resync_pages offset
Mike Snitzer snitzer@redhat.com Revert "dm crypt: use WQ_HIGHPRI for the IO and crypt workqueues"
Adam Ford aford173@gmail.com Revert "Bluetooth: hci_ll: set operational frequency earlier"
Denis Efremov efremov@linux.com ath9k_hw: fix uninitialized variable data
Hui Peng benquike@gmail.com ath10k: Fix a NULL-ptr-deref bug in ath10k_usb_alloc_urb_from_pipe
Bjorn Andersson bjorn.andersson@linaro.org ath10k: Fix HOST capability QMI incompatibility
Christian Lamparter chunkeey@gmail.com ath10k: restore QCA9880-AR1A (v1) detection
Tomas Bortoli tomasbortoli@gmail.com Bluetooth: Fix invalid-free in bcsp_close()
Chris Wilson chris@chris-wilson.co.uk drm/i915/userptr: Try to acquire the page lock around set_page_dirty()
Chris Wilson chris@chris-wilson.co.uk drm/i915/pmu: "Frequency" is reported as accumulated cycles
Ville Syrjälä ville.syrjala@linux.intel.com drm/i915: Don't oops in dumb_create ioctl if we have no crtcs
Evan Quan evan.quan@amd.com drm/amd/powerplay: issue no PPSMC_MSG_GetCurrPkgPwr on unsupported ASICs
Alex Deucher alexander.deucher@amd.com drm/amdgpu: disable gfxoff on original raven
Alex Deucher alexander.deucher@amd.com drm/amdgpu: disable gfxoff when using register read interface
Andrey Ryabinin aryabinin@virtuozzo.com mm/ksm.c: don't WARN if page is still mapped in remove_stable_node()
David Hildenbrand david@redhat.com mm/memory_hotplug: don't access uninitialized memmaps in shrink_zone_span()
Joseph Qi joseph.qi@linux.alibaba.com Revert "fs: ocfs2: fix possible null-pointer dereferences in ocfs2_xa_prepare_entry()"
Wei Wang wei.w.wang@intel.com virtio_balloon: fix shrinker count
Halil Pasic pasic@linux.ibm.com virtio_ring: fix return code on DMA mapping fails
Laurent Vivier lvivier@redhat.com virtio_console: allocate inbufs in add_port() only if it is needed
Sun Ke sunke32@huawei.com nbd:fix memory leak in nbd_get_socket()
Luc Van Oostenryck luc.vanoostenryck@gmail.com fork: fix pidfd_poll()'s return type
Laura Abbott labbott@redhat.com tools: gpio: Correctly add make dependencies for gpio_utils
Thierry Reding treding@nvidia.com gpio: bd70528: Use correct unit for debounce times
Thierry Reding treding@nvidia.com gpio: max77620: Fixup debounce delays
Stefano Garzarella sgarzare@redhat.com vhost/vsock: split packets to send using multiple buffers
Shani Shapp shanish@mellanox.com net/mlx5: Update the list of the PCI supported devices
Eran Ben Elisha eranbe@mellanox.com net/mlx5e: Do not use non-EXT link modes in EXT mode
Eli Cohen eli@mellanox.com net/mlx5e: Fix error flow cleanup in mlx5e_tc_tun_create_header_ipv4/6
Marcelo Ricardo Leitner marcelo.leitner@gmail.com net/ipv4: fix sysctl max for fib_multipath_hash_policy
Ivan Khoronzhuk ivan.khoronzhuk@linaro.org taprio: don't reject same mqprio settings
Hangbin Liu liuhangbin@gmail.com ipv6/route: return if there is no fib_nh_gw_family
Willem de Bruijn willemb@google.com net/tls: enable sk_msg redirect to tls socket egress
Maor Gottlieb maorg@mellanox.com net/mlx5: Fix auto group size calculation
Roi Dayan roid@mellanox.com net/mlx5e: Fix set vf link state error flow
Eran Ben Elisha eranbe@mellanox.com net/mlxfw: Verify FSM error code translation doesn't exceed array size
Martin Habets mhabets@solarflare.com sfc: Only cancel the PPS workqueue if it exists
Xin Long lucien.xin@gmail.com net: sched: ensure opts_len <= IP_TUNNEL_OPTS_MAX in act_tunnel_key
Davide Caratti dcaratti@redhat.com net/sched: act_pedit: fix WARN() in the traffic path
Dan Carpenter dan.carpenter@oracle.com net: rtnetlink: prevent underflows in do_setvfinfo()
Tariq Toukan tariqt@mellanox.com net/mlx4_en: Fix wrong limitation for number of TX rings
Luigi Rizzo lrizzo@google.com net/mlx4_en: fix mlx4 ethtool -N insertion
Petr Machata petrm@mellanox.com mlxsw: spectrum_router: Fix determining underlay for a GRE tunnel
-------------
Diffstat:
Documentation/admin-guide/hw-vuln/mds.rst | 7 +- .../admin-guide/hw-vuln/tsx_async_abort.rst | 5 +- Documentation/admin-guide/kernel-parameters.txt | 11 ++ .../bindings/net/wireless/qcom,ath10k.txt | 6 + Makefile | 4 +- arch/arm/mm/mmu.c | 3 + arch/powerpc/include/asm/asm-prototypes.h | 3 + arch/powerpc/include/asm/security_features.h | 3 + arch/powerpc/kernel/entry_64.S | 6 + arch/powerpc/kernel/security.c | 74 +++++++- arch/powerpc/kvm/book3s_hv_rmhandlers.S | 30 +++ arch/x86/entry/entry_32.S | 211 +++++++++++++-------- arch/x86/include/asm/cpu_entry_area.h | 18 +- arch/x86/include/asm/pgtable_32_types.h | 8 +- arch/x86/include/asm/segment.h | 12 ++ arch/x86/kernel/cpu/bugs.c | 30 ++- arch/x86/kernel/doublefault.c | 3 + arch/x86/kernel/head_32.S | 10 + arch/x86/mm/cpu_entry_area.c | 4 +- arch/x86/tools/gen-insn-attr-x86.awk | 4 +- arch/x86/xen/xen-asm_32.S | 75 +++----- drivers/block/nbd.c | 6 +- drivers/bluetooth/hci_bcsp.c | 3 + drivers/bluetooth/hci_ll.c | 39 ++-- drivers/char/virtio_console.c | 28 ++- drivers/cpufreq/cpufreq.c | 6 + drivers/gpio/gpio-bd70528.c | 6 +- drivers/gpio/gpio-max77620.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 6 +- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 9 +- drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | 23 ++- drivers/gpu/drm/i915/display/intel_display.c | 3 + drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 22 ++- drivers/gpu/drm/i915/i915_pmu.c | 4 +- drivers/md/dm-crypt.c | 9 +- drivers/md/raid10.c | 2 +- drivers/media/platform/vivid/vivid-kthread-cap.c | 8 +- drivers/media/platform/vivid/vivid-kthread-out.c | 8 +- drivers/media/platform/vivid/vivid-sdr-cap.c | 8 +- drivers/media/platform/vivid/vivid-vid-cap.c | 3 - drivers/media/platform/vivid/vivid-vid-out.c | 3 - drivers/media/rc/imon.c | 3 +- drivers/media/rc/mceusb.c | 141 +++++++++----- drivers/media/usb/b2c2/flexcop-usb.c | 3 + drivers/media/usb/dvb-usb/cxusb.c | 3 +- drivers/media/usb/usbvision/usbvision-video.c | 29 ++- drivers/media/usb/uvc/uvc_driver.c | 28 +-- drivers/net/ethernet/google/gve/gve_tx.c | 9 +- drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 9 +- drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 9 + .../net/ethernet/mellanox/mlx5/core/en/tc_tun.c | 18 +- .../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 12 +- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 10 +- drivers/net/ethernet/mellanox/mlx5/core/fs_core.h | 1 + drivers/net/ethernet/mellanox/mlx5/core/main.c | 1 + drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c | 2 + .../net/ethernet/mellanox/mlxsw/spectrum_router.c | 19 +- drivers/net/ethernet/sfc/ptp.c | 3 +- drivers/net/phy/mdio_bus.c | 11 +- drivers/net/wireless/ath/ath10k/pci.c | 36 ++-- drivers/net/wireless/ath/ath10k/qmi.c | 13 +- drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c | 22 +++ drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h | 1 + drivers/net/wireless/ath/ath10k/snoc.c | 11 ++ drivers/net/wireless/ath/ath10k/snoc.h | 1 + drivers/net/wireless/ath/ath10k/usb.c | 8 + drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2 +- drivers/nfc/port100.c | 2 +- drivers/staging/comedi/drivers/usbduxfast.c | 21 +- drivers/usb/misc/appledisplay.c | 8 +- drivers/usb/misc/chaoskey.c | 24 ++- drivers/usb/serial/cp210x.c | 1 + drivers/usb/serial/mos7720.c | 4 - drivers/usb/serial/mos7840.c | 16 +- drivers/usb/serial/option.c | 7 + drivers/usb/usbip/Kconfig | 1 + drivers/usb/usbip/stub_rx.c | 50 +++-- drivers/vhost/vsock.c | 66 +++++-- drivers/virtio/virtio_balloon.c | 2 +- drivers/virtio/virtio_ring.c | 4 +- fs/ocfs2/xattr.c | 56 +++--- include/net/tls.h | 2 + kernel/fork.c | 6 +- kernel/futex.c | 58 +++++- mm/ksm.c | 14 +- mm/memory_hotplug.c | 16 +- mm/slub.c | 22 ++- net/core/net-sysfs.c | 24 +-- net/core/rtnetlink.c | 23 ++- net/ipv4/sysctl_net_ipv4.c | 2 +- net/ipv6/route.c | 2 +- net/sched/act_pedit.c | 12 +- net/sched/act_tunnel_key.c | 4 + net/sched/sch_taprio.c | 28 ++- net/tls/tls_main.c | 1 + net/tls/tls_sw.c | 11 ++ net/vmw_vsock/virtio_transport_common.c | 15 +- sound/usb/mixer.c | 3 + tools/gpio/Build | 1 + tools/gpio/Makefile | 10 +- tools/objtool/arch/x86/tools/gen-insn-attr-x86.awk | 4 +- tools/testing/selftests/x86/mov_ss_trap.c | 3 +- tools/testing/selftests/x86/sigreturn.c | 13 ++ tools/usb/usbip/libsrc/usbip_host_common.c | 2 +- 105 files changed, 1173 insertions(+), 501 deletions(-)
From: Petr Machata petrm@mellanox.com
[ Upstream commit 1fc1657775dc1b19e9ac1d46b4054ed8ae5d99ab ]
The helper mlxsw_sp_ipip_dev_ul_tb_id() determines the underlay VRF of a GRE tunnel. For a tunnel without a bound device, it uses the same VRF that the tunnel is in. However in Linux, a GRE tunnel without a bound device uses the main VRF as the underlay. Fix the function accordingly.
mlxsw further assumed that moving a tunnel to a different VRF could cause conflict in local tunnel endpoint address, which cannot be offloaded. However, the only way that an underlay could be changed by moving the tunnel device itself is if the tunnel device does not have a bound device. But in that case the underlay is always the main VRF, so there is no opportunity to introduce a conflict by moving such device. Thus this check constitutes a dead code, and can be removed, which do.
Fixes: 6ddb7426a7d4 ("mlxsw: spectrum_router: Introduce loopback RIFs") Signed-off-by: Petr Machata petrm@mellanox.com Signed-off-by: Ido Schimmel idosch@mellanox.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 19 ------------------ 1 file changed, 1 insertion(+), 18 deletions(-)
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -994,7 +994,7 @@ u32 mlxsw_sp_ipip_dev_ul_tb_id(const str if (d) return l3mdev_fib_table(d) ? : RT_TABLE_MAIN; else - return l3mdev_fib_table(ol_dev) ? : RT_TABLE_MAIN; + return RT_TABLE_MAIN; }
static struct mlxsw_sp_rif * @@ -1598,27 +1598,10 @@ static int mlxsw_sp_netdevice_ipip_ol_vr { struct mlxsw_sp_ipip_entry *ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev); - enum mlxsw_sp_l3proto ul_proto; - union mlxsw_sp_l3addr saddr; - u32 ul_tb_id;
if (!ipip_entry) return 0;
- /* For flat configuration cases, moving overlay to a different VRF might - * cause local address conflict, and the conflicting tunnels need to be - * demoted. - */ - ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ol_dev); - ul_proto = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt]->ul_proto; - saddr = mlxsw_sp_ipip_netdev_saddr(ul_proto, ol_dev); - if (mlxsw_sp_ipip_demote_tunnel_by_saddr(mlxsw_sp, ul_proto, - saddr, ul_tb_id, - ipip_entry)) { - mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp, ipip_entry); - return 0; - } - return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry, true, false, false, extack); }
From: Luigi Rizzo lrizzo@google.com
[ Upstream commit 34e59836565e36fade1464e054a3551c1a0364be ]
ethtool expects ETHTOOL_GRXCLSRLALL to set ethtool_rxnfc->data with the total number of entries in the rx classifier table. Surprisingly, mlx4 is missing this part (in principle ethtool could still move forward and try the insert).
Tested: compiled and run command: phh13:~# ethtool -N eth1 flow-type udp4 queue 4 Added rule with ID 255
Signed-off-by: Luigi Rizzo lrizzo@google.com Reviewed-by: Tariq Toukan tariqt@mellanox.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c @@ -1745,6 +1745,7 @@ static int mlx4_en_get_rxnfc(struct net_ err = mlx4_en_get_flow(dev, cmd, cmd->fs.location); break; case ETHTOOL_GRXCLSRLALL: + cmd->data = MAX_NUM_OF_FS_RULES; while ((!err || err == -ENOENT) && priority < cmd->rule_cnt) { err = mlx4_en_get_flow(dev, cmd, i); if (!err)
From: Tariq Toukan tariqt@mellanox.com
[ Upstream commit 2744bf42680f64ebf2ee8a00354897857c073331 ]
XDP_TX rings should not be limited by max_num_tx_rings_p_up. To make sure total number of TX rings never exceed MAX_TX_RINGS, add similar check in mlx4_en_alloc_tx_queue_per_tc(), where a new value is assigned for num_up.
Fixes: 7e1dc5e926d5 ("net/mlx4_en: Limit the number of TX rings") Signed-off-by: Tariq Toukan tariqt@mellanox.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 8 ++++---- drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 9 +++++++++ 2 files changed, 13 insertions(+), 4 deletions(-)
--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c @@ -1812,6 +1812,7 @@ static int mlx4_en_set_channels(struct n struct mlx4_en_dev *mdev = priv->mdev; struct mlx4_en_port_profile new_prof; struct mlx4_en_priv *tmp; + int total_tx_count; int port_up = 0; int xdp_count; int err = 0; @@ -1826,13 +1827,12 @@ static int mlx4_en_set_channels(struct n
mutex_lock(&mdev->state_lock); xdp_count = priv->tx_ring_num[TX_XDP] ? channel->rx_count : 0; - if (channel->tx_count * priv->prof->num_up + xdp_count > - priv->mdev->profile.max_num_tx_rings_p_up * priv->prof->num_up) { + total_tx_count = channel->tx_count * priv->prof->num_up + xdp_count; + if (total_tx_count > MAX_TX_RINGS) { err = -EINVAL; en_err(priv, "Total number of TX and XDP rings (%d) exceeds the maximum supported (%d)\n", - channel->tx_count * priv->prof->num_up + xdp_count, - MAX_TX_RINGS); + total_tx_count, MAX_TX_RINGS); goto out; }
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -91,6 +91,7 @@ int mlx4_en_alloc_tx_queue_per_tc(struct struct mlx4_en_dev *mdev = priv->mdev; struct mlx4_en_port_profile new_prof; struct mlx4_en_priv *tmp; + int total_count; int port_up = 0; int err = 0;
@@ -104,6 +105,14 @@ int mlx4_en_alloc_tx_queue_per_tc(struct MLX4_EN_NUM_UP_HIGH; new_prof.tx_ring_num[TX] = new_prof.num_tx_rings_p_up * new_prof.num_up; + total_count = new_prof.tx_ring_num[TX] + new_prof.tx_ring_num[TX_XDP]; + if (total_count > MAX_TX_RINGS) { + err = -EINVAL; + en_err(priv, + "Total number of TX and XDP rings (%d) exceeds the maximum supported (%d)\n", + total_count, MAX_TX_RINGS); + goto out; + } err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof, true); if (err) goto out;
From: Dan Carpenter dan.carpenter@oracle.com
[ Upstream commit d658c8f56ec7b3de8051a24afb25da9ba3c388c5 ]
The "ivm->vf" variable is a u32, but the problem is that a number of drivers cast it to an int and then forget to check for negatives. An example of this is in the cxgb4 driver.
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c 2890 static int cxgb4_mgmt_get_vf_config(struct net_device *dev, 2891 int vf, struct ifla_vf_info *ivi) ^^^^^^ 2892 { 2893 struct port_info *pi = netdev_priv(dev); 2894 struct adapter *adap = pi->adapter; 2895 struct vf_info *vfinfo; 2896 2897 if (vf >= adap->num_vfs) ^^^^^^^^^^^^^^^^^^^ 2898 return -EINVAL; 2899 vfinfo = &adap->vfinfo[vf]; ^^^^^^^^^^^^^^^^^^^^^^^^^^
There are 48 functions affected.
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c:8435 hclge_set_vf_vlan_filter() warn: can 'vfid' underflow 's32min-2147483646' drivers/net/ethernet/freescale/enetc/enetc_pf.c:377 enetc_pf_set_vf_mac() warn: can 'vf' underflow 's32min-2147483646' drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c:2899 cxgb4_mgmt_get_vf_config() warn: can 'vf' underflow 's32min-254' drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c:2960 cxgb4_mgmt_set_vf_rate() warn: can 'vf' underflow 's32min-254' drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c:3019 cxgb4_mgmt_set_vf_rate() warn: can 'vf' underflow 's32min-254' drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c:3038 cxgb4_mgmt_set_vf_vlan() warn: can 'vf' underflow 's32min-254' drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c:3086 cxgb4_mgmt_set_vf_link_state() warn: can 'vf' underflow 's32min-254' drivers/net/ethernet/chelsio/cxgb/cxgb2.c:791 get_eeprom() warn: can 'i' underflow 's32min-(-4),0,4-s32max' drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c:82 bnxt_set_vf_spoofchk() warn: can 'vf_id' underflow 's32min-65534' drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c:164 bnxt_set_vf_trust() warn: can 'vf_id' underflow 's32min-65534' drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c:186 bnxt_get_vf_config() warn: can 'vf_id' underflow 's32min-65534' drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c:228 bnxt_set_vf_mac() warn: can 'vf_id' underflow 's32min-65534' drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c:264 bnxt_set_vf_vlan() warn: can 'vf_id' underflow 's32min-65534' drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c:293 bnxt_set_vf_bw() warn: can 'vf_id' underflow 's32min-65534' drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c:333 bnxt_set_vf_link_state() warn: can 'vf_id' underflow 's32min-65534' drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c:2595 bnx2x_vf_op_prep() warn: can 'vfidx' underflow 's32min-63' drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c:2595 bnx2x_vf_op_prep() warn: can 'vfidx' underflow 's32min-63' drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c:2281 bnx2x_post_vf_bulletin() warn: can 'vf' underflow 's32min-63' drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c:2285 bnx2x_post_vf_bulletin() warn: can 'vf' underflow 's32min-63' drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c:2286 bnx2x_post_vf_bulletin() warn: can 'vf' underflow 's32min-63' drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c:2292 bnx2x_post_vf_bulletin() warn: can 'vf' underflow 's32min-63' drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c:2297 bnx2x_post_vf_bulletin() warn: can 'vf' underflow 's32min-63' drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c:1832 qlcnic_sriov_set_vf_mac() warn: can 'vf' underflow 's32min-254' drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c:1864 qlcnic_sriov_set_vf_tx_rate() warn: can 'vf' underflow 's32min-254' drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c:1937 qlcnic_sriov_set_vf_vlan() warn: can 'vf' underflow 's32min-254' drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c:2005 qlcnic_sriov_get_vf_config() warn: can 'vf' underflow 's32min-254' drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c:2036 qlcnic_sriov_set_vf_spoofchk() warn: can 'vf' underflow 's32min-254' drivers/net/ethernet/emulex/benet/be_main.c:1914 be_get_vf_config() warn: can 'vf' underflow 's32min-65534' drivers/net/ethernet/emulex/benet/be_main.c:1915 be_get_vf_config() warn: can 'vf' underflow 's32min-65534' drivers/net/ethernet/emulex/benet/be_main.c:1922 be_set_vf_tvt() warn: can 'vf' underflow 's32min-65534' drivers/net/ethernet/emulex/benet/be_main.c:1951 be_clear_vf_tvt() warn: can 'vf' underflow 's32min-65534' drivers/net/ethernet/emulex/benet/be_main.c:2063 be_set_vf_tx_rate() warn: can 'vf' underflow 's32min-65534' drivers/net/ethernet/emulex/benet/be_main.c:2091 be_set_vf_link_state() warn: can 'vf' underflow 's32min-65534' drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c:2609 ice_set_vf_port_vlan() warn: can 'vf_id' underflow 's32min-65534' drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c:3050 ice_get_vf_cfg() warn: can 'vf_id' underflow 's32min-65534' drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c:3103 ice_set_vf_spoofchk() warn: can 'vf_id' underflow 's32min-65534' drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c:3181 ice_set_vf_mac() warn: can 'vf_id' underflow 's32min-65534' drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c:3237 ice_set_vf_trust() warn: can 'vf_id' underflow 's32min-65534' drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c:3286 ice_set_vf_link_state() warn: can 'vf_id' underflow 's32min-65534' drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c:3919 i40e_validate_vf() warn: can 'vf_id' underflow 's32min-2147483646' drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c:3957 i40e_ndo_set_vf_mac() warn: can 'vf_id' underflow 's32min-2147483646' drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c:4104 i40e_ndo_set_vf_port_vlan() warn: can 'vf_id' underflow 's32min-2147483646' drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c:4263 i40e_ndo_set_vf_bw() warn: can 'vf_id' underflow 's32min-2147483646' drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c:4309 i40e_ndo_get_vf_config() warn: can 'vf_id' underflow 's32min-2147483646' drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c:4371 i40e_ndo_set_vf_link_state() warn: can 'vf_id' underflow 's32min-2147483646' drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c:4441 i40e_ndo_set_vf_spoofchk() warn: can 'vf_id' underflow 's32min-2147483646' drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c:4441 i40e_ndo_set_vf_spoofchk() warn: can 'vf_id' underflow 's32min-2147483646' drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c:4504 i40e_ndo_set_vf_trust() warn: can 'vf_id' underflow 's32min-2147483646'
Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/core/rtnetlink.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-)
--- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -2195,6 +2195,8 @@ static int do_setvfinfo(struct net_devic if (tb[IFLA_VF_MAC]) { struct ifla_vf_mac *ivm = nla_data(tb[IFLA_VF_MAC]);
+ if (ivm->vf >= INT_MAX) + return -EINVAL; err = -EOPNOTSUPP; if (ops->ndo_set_vf_mac) err = ops->ndo_set_vf_mac(dev, ivm->vf, @@ -2206,6 +2208,8 @@ static int do_setvfinfo(struct net_devic if (tb[IFLA_VF_VLAN]) { struct ifla_vf_vlan *ivv = nla_data(tb[IFLA_VF_VLAN]);
+ if (ivv->vf >= INT_MAX) + return -EINVAL; err = -EOPNOTSUPP; if (ops->ndo_set_vf_vlan) err = ops->ndo_set_vf_vlan(dev, ivv->vf, ivv->vlan, @@ -2238,6 +2242,8 @@ static int do_setvfinfo(struct net_devic if (len == 0) return -EINVAL;
+ if (ivvl[0]->vf >= INT_MAX) + return -EINVAL; err = ops->ndo_set_vf_vlan(dev, ivvl[0]->vf, ivvl[0]->vlan, ivvl[0]->qos, ivvl[0]->vlan_proto); if (err < 0) @@ -2248,6 +2254,8 @@ static int do_setvfinfo(struct net_devic struct ifla_vf_tx_rate *ivt = nla_data(tb[IFLA_VF_TX_RATE]); struct ifla_vf_info ivf;
+ if (ivt->vf >= INT_MAX) + return -EINVAL; err = -EOPNOTSUPP; if (ops->ndo_get_vf_config) err = ops->ndo_get_vf_config(dev, ivt->vf, &ivf); @@ -2266,6 +2274,8 @@ static int do_setvfinfo(struct net_devic if (tb[IFLA_VF_RATE]) { struct ifla_vf_rate *ivt = nla_data(tb[IFLA_VF_RATE]);
+ if (ivt->vf >= INT_MAX) + return -EINVAL; err = -EOPNOTSUPP; if (ops->ndo_set_vf_rate) err = ops->ndo_set_vf_rate(dev, ivt->vf, @@ -2278,6 +2288,8 @@ static int do_setvfinfo(struct net_devic if (tb[IFLA_VF_SPOOFCHK]) { struct ifla_vf_spoofchk *ivs = nla_data(tb[IFLA_VF_SPOOFCHK]);
+ if (ivs->vf >= INT_MAX) + return -EINVAL; err = -EOPNOTSUPP; if (ops->ndo_set_vf_spoofchk) err = ops->ndo_set_vf_spoofchk(dev, ivs->vf, @@ -2289,6 +2301,8 @@ static int do_setvfinfo(struct net_devic if (tb[IFLA_VF_LINK_STATE]) { struct ifla_vf_link_state *ivl = nla_data(tb[IFLA_VF_LINK_STATE]);
+ if (ivl->vf >= INT_MAX) + return -EINVAL; err = -EOPNOTSUPP; if (ops->ndo_set_vf_link_state) err = ops->ndo_set_vf_link_state(dev, ivl->vf, @@ -2302,6 +2316,8 @@ static int do_setvfinfo(struct net_devic
err = -EOPNOTSUPP; ivrssq_en = nla_data(tb[IFLA_VF_RSS_QUERY_EN]); + if (ivrssq_en->vf >= INT_MAX) + return -EINVAL; if (ops->ndo_set_vf_rss_query_en) err = ops->ndo_set_vf_rss_query_en(dev, ivrssq_en->vf, ivrssq_en->setting); @@ -2312,6 +2328,8 @@ static int do_setvfinfo(struct net_devic if (tb[IFLA_VF_TRUST]) { struct ifla_vf_trust *ivt = nla_data(tb[IFLA_VF_TRUST]);
+ if (ivt->vf >= INT_MAX) + return -EINVAL; err = -EOPNOTSUPP; if (ops->ndo_set_vf_trust) err = ops->ndo_set_vf_trust(dev, ivt->vf, ivt->setting); @@ -2322,15 +2340,18 @@ static int do_setvfinfo(struct net_devic if (tb[IFLA_VF_IB_NODE_GUID]) { struct ifla_vf_guid *ivt = nla_data(tb[IFLA_VF_IB_NODE_GUID]);
+ if (ivt->vf >= INT_MAX) + return -EINVAL; if (!ops->ndo_set_vf_guid) return -EOPNOTSUPP; - return handle_vf_guid(dev, ivt, IFLA_VF_IB_NODE_GUID); }
if (tb[IFLA_VF_IB_PORT_GUID]) { struct ifla_vf_guid *ivt = nla_data(tb[IFLA_VF_IB_PORT_GUID]);
+ if (ivt->vf >= INT_MAX) + return -EINVAL; if (!ops->ndo_set_vf_guid) return -EOPNOTSUPP;
From: Davide Caratti dcaratti@redhat.com
[ Upstream commit f67169fef8dbcc1ac6a6a109ecaad0d3b259002c ]
when configuring act_pedit rules, the number of keys is validated only on addition of a new entry. This is not sufficient to avoid hitting a WARN() in the traffic path: for example, it is possible to replace a valid entry with a new one having 0 extended keys, thus causing splats in dmesg like:
pedit BUG: index 42 WARNING: CPU: 2 PID: 4054 at net/sched/act_pedit.c:410 tcf_pedit_act+0xc84/0x1200 [act_pedit] [...] RIP: 0010:tcf_pedit_act+0xc84/0x1200 [act_pedit] Code: 89 fa 48 c1 ea 03 0f b6 04 02 84 c0 74 08 3c 03 0f 8e ac 00 00 00 48 8b 44 24 10 48 c7 c7 a0 c4 e4 c0 8b 70 18 e8 1c 30 95 ea <0f> 0b e9 a0 fa ff ff e8 00 03 f5 ea e9 14 f4 ff ff 48 89 58 40 e9 RSP: 0018:ffff888077c9f320 EFLAGS: 00010286 RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffffffffac2983a2 RDX: 0000000000000001 RSI: 0000000000000008 RDI: ffff888053927bec RBP: dffffc0000000000 R08: ffffed100a726209 R09: ffffed100a726209 R10: 0000000000000001 R11: ffffed100a726208 R12: ffff88804beea780 R13: ffff888079a77400 R14: ffff88804beea780 R15: ffff888027ab2000 FS: 00007fdeec9bd740(0000) GS:ffff888053900000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007ffdb3dfd000 CR3: 000000004adb4006 CR4: 00000000001606e0 Call Trace: tcf_action_exec+0x105/0x3f0 tcf_classify+0xf2/0x410 __dev_queue_xmit+0xcbf/0x2ae0 ip_finish_output2+0x711/0x1fb0 ip_output+0x1bf/0x4b0 ip_send_skb+0x37/0xa0 raw_sendmsg+0x180c/0x2430 sock_sendmsg+0xdb/0x110 __sys_sendto+0x257/0x2b0 __x64_sys_sendto+0xdd/0x1b0 do_syscall_64+0xa5/0x4e0 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x7fdeeb72e993 Code: 48 8b 0d e0 74 2c 00 f7 d8 64 89 01 48 83 c8 ff c3 66 0f 1f 44 00 00 83 3d 0d d6 2c 00 00 75 13 49 89 ca b8 2c 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 34 c3 48 83 ec 08 e8 4b cc 00 00 48 89 04 24 RSP: 002b:00007ffdb3de8a18 EFLAGS: 00000246 ORIG_RAX: 000000000000002c RAX: ffffffffffffffda RBX: 000055c81972b700 RCX: 00007fdeeb72e993 RDX: 0000000000000040 RSI: 000055c81972b700 RDI: 0000000000000003 RBP: 00007ffdb3dea130 R08: 000055c819728510 R09: 0000000000000010 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000040 R13: 000055c81972b6c0 R14: 000055c81972969c R15: 0000000000000080
Fix this moving the check on 'nkeys' earlier in tcf_pedit_init(), so that attempts to install rules having 0 keys are always rejected with -EINVAL.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Davide Caratti dcaratti@redhat.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/sched/act_pedit.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-)
--- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c @@ -43,7 +43,7 @@ static struct tcf_pedit_key_ex *tcf_pedi int err = -EINVAL; int rem;
- if (!nla || !n) + if (!nla) return NULL;
keys_ex = kcalloc(n, sizeof(*k), GFP_KERNEL); @@ -170,6 +170,10 @@ static int tcf_pedit_init(struct net *ne }
parm = nla_data(pattr); + if (!parm->nkeys) { + NL_SET_ERR_MSG_MOD(extack, "Pedit requires keys to be passed"); + return -EINVAL; + } ksize = parm->nkeys * sizeof(struct tc_pedit_key); if (nla_len(pattr) < sizeof(*parm) + ksize) { NL_SET_ERR_MSG_ATTR(extack, pattr, "Length of TCA_PEDIT_PARMS or TCA_PEDIT_PARMS_EX pedit attribute is invalid"); @@ -183,12 +187,6 @@ static int tcf_pedit_init(struct net *ne index = parm->index; err = tcf_idr_check_alloc(tn, &index, a, bind); if (!err) { - if (!parm->nkeys) { - tcf_idr_cleanup(tn, index); - NL_SET_ERR_MSG_MOD(extack, "Pedit requires keys to be passed"); - ret = -EINVAL; - goto out_free; - } ret = tcf_idr_create(tn, index, est, a, &act_pedit_ops, bind, false); if (ret) {
From: Xin Long lucien.xin@gmail.com
[ Upstream commit 4f0e97d070984d487df027f163e52bb72d1713d8 ]
info->options_len is 'u8' type, and when opts_len with a value > IP_TUNNEL_OPTS_MAX, 'info->options_len = opts_len' will cast int to u8 and set a wrong value to info->options_len.
Kernel crashed in my test when doing:
# opts="0102:80:00800022" # for i in {1..99}; do opts="$opts,0102:80:00800022"; done # ip link add name geneve0 type geneve dstport 0 external # tc qdisc add dev eth0 ingress # tc filter add dev eth0 protocol ip parent ffff: \ flower indev eth0 ip_proto udp action tunnel_key \ set src_ip 10.0.99.192 dst_ip 10.0.99.193 \ dst_port 6081 id 11 geneve_opts $opts \ action mirred egress redirect dev geneve0
So we should do the similar check as cls_flower does, return error when opts_len > IP_TUNNEL_OPTS_MAX in tunnel_key_copy_opts().
Fixes: 0ed5269f9e41 ("net/sched: add tunnel option support to act_tunnel_key") Signed-off-by: Xin Long lucien.xin@gmail.com Reviewed-by: Simon Horman simon.horman@netronome.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/sched/act_tunnel_key.c | 4 ++++ 1 file changed, 4 insertions(+)
--- a/net/sched/act_tunnel_key.c +++ b/net/sched/act_tunnel_key.c @@ -135,6 +135,10 @@ static int tunnel_key_copy_opts(const st if (opt_len < 0) return opt_len; opts_len += opt_len; + if (opts_len > IP_TUNNEL_OPTS_MAX) { + NL_SET_ERR_MSG(extack, "Tunnel options exceeds max size"); + return -EINVAL; + } if (dst) { dst_len -= opt_len; dst += opt_len;
From: Martin Habets mhabets@solarflare.com
[ Upstream commit 723eb53690041740a13ac78efeaf6804f5d684c9 ]
The workqueue only exists for the primary PF. For other functions we hit a WARN_ON in kernel/workqueue.c.
Fixes: 7c236c43b838 ("sfc: Add support for IEEE-1588 PTP") Signed-off-by: Martin Habets mhabets@solarflare.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/ethernet/sfc/ptp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -1531,7 +1531,8 @@ void efx_ptp_remove(struct efx_nic *efx) (void)efx_ptp_disable(efx);
cancel_work_sync(&efx->ptp_data->work); - cancel_work_sync(&efx->ptp_data->pps_work); + if (efx->ptp_data->pps_workwq) + cancel_work_sync(&efx->ptp_data->pps_work);
skb_queue_purge(&efx->ptp_data->rxq); skb_queue_purge(&efx->ptp_data->txq);
From: Eran Ben Elisha eranbe@mellanox.com
[ Upstream commit 30e9e0550bf693c94bc15827781fe42dd60be634 ]
Array mlxfw_fsm_state_err_str contains value to string translation, when values are provided by mlxfw_dev. If value is larger than MLXFW_FSM_STATE_ERR_MAX, return "unknown error" as expected instead of reading an address than exceed array size.
Fixes: 410ed13cae39 ("Add the mlxfw module for Mellanox firmware flash process") Signed-off-by: Eran Ben Elisha eranbe@mellanox.com Acked-by: Jiri Pirko jiri@mellanox.com Signed-off-by: Saeed Mahameed saeedm@mellanox.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c | 2 ++ 1 file changed, 2 insertions(+)
--- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c +++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c @@ -66,6 +66,8 @@ retry: return err;
if (fsm_state_err != MLXFW_FSM_STATE_ERR_OK) { + fsm_state_err = min_t(enum mlxfw_fsm_state_err, + fsm_state_err, MLXFW_FSM_STATE_ERR_MAX); pr_err("Firmware flash failed: %s\n", mlxfw_fsm_state_err_str[fsm_state_err]); NL_SET_ERR_MSG_MOD(extack, "Firmware flash failed");
From: Roi Dayan roid@mellanox.com
[ Upstream commit 751021218f7e66ee9bbaa2be23056e447cd75ec4 ]
Before this commit the ndo always returned success. Fix that.
Fixes: 1ab2068a4c66 ("net/mlx5: Implement vports admin state backup/restore") Signed-off-by: Roi Dayan roid@mellanox.com Reviewed-by: Vlad Buslov vladbu@mellanox.com Signed-off-by: Saeed Mahameed saeedm@mellanox.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -2044,7 +2044,7 @@ int mlx5_eswitch_set_vport_state(struct
unlock: mutex_unlock(&esw->state_lock); - return 0; + return err; }
int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,
From: Maor Gottlieb maorg@mellanox.com
[ Upstream commit 97fd8da281f80e7e69e0114bc906575734d4dfaf ]
Once all the large flow groups (defined by the user when the flow table is created - max_num_groups) were created, then all the following new flow groups will have only one flow table entry, even though the flow table has place to larger groups. Fix the condition to prefer large flow group.
Fixes: f0d22d187473 ("net/mlx5_core: Introduce flow steering autogrouped flow table") Signed-off-by: Maor Gottlieb maorg@mellanox.com Signed-off-by: Saeed Mahameed saeedm@mellanox.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 10 ++++++---- drivers/net/ethernet/mellanox/mlx5/core/fs_core.h | 1 + 2 files changed, 7 insertions(+), 4 deletions(-)
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -549,7 +549,7 @@ static void del_sw_flow_group(struct fs_
rhashtable_destroy(&fg->ftes_hash); ida_destroy(&fg->fte_allocator); - if (ft->autogroup.active) + if (ft->autogroup.active && fg->max_ftes == ft->autogroup.group_size) ft->autogroup.num_groups--; err = rhltable_remove(&ft->fgs_hash, &fg->hash, @@ -1095,6 +1095,8 @@ mlx5_create_auto_grouped_flow_table(stru
ft->autogroup.active = true; ft->autogroup.required_groups = max_num_groups; + /* We save place for flow groups in addition to max types */ + ft->autogroup.group_size = ft->max_fte / (max_num_groups + 1);
return ft; } @@ -1297,8 +1299,7 @@ static struct mlx5_flow_group *alloc_aut return ERR_PTR(-ENOENT);
if (ft->autogroup.num_groups < ft->autogroup.required_groups) - /* We save place for flow groups in addition to max types */ - group_size = ft->max_fte / (ft->autogroup.required_groups + 1); + group_size = ft->autogroup.group_size;
/* ft->max_fte == ft->autogroup.max_types */ if (group_size == 0) @@ -1325,7 +1326,8 @@ static struct mlx5_flow_group *alloc_aut if (IS_ERR(fg)) goto out;
- ft->autogroup.num_groups++; + if (group_size == ft->autogroup.group_size) + ft->autogroup.num_groups++;
out: return fg; --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h @@ -137,6 +137,7 @@ struct mlx5_flow_table { struct { bool active; unsigned int required_groups; + unsigned int group_size; unsigned int num_groups; } autogroup; /* Protect fwd_rules */
From: Willem de Bruijn willemb@google.com
[ Upstream commit d4ffb02dee2fcb20e0c8086a8d1305bf885820bb ]
Bring back tls_sw_sendpage_locked. sk_msg redirection into a socket with TLS_TX takes the following path:
tcp_bpf_sendmsg_redir tcp_bpf_push_locked tcp_bpf_push kernel_sendpage_locked sock->ops->sendpage_locked
Also update the flags test in tls_sw_sendpage_locked to allow flag MSG_NO_SHARED_FRAGS. bpf_tcp_sendmsg sets this.
Link: https://lore.kernel.org/netdev/CA+FuTSdaAawmZ2N8nfDDKu3XLpXBbMtcCT0q4FntDD2g... Link: https://github.com/wdebruij/kerneltools/commits/icept.2 Fixes: 0608c69c9a80 ("bpf: sk_msg, sock{map|hash} redirect through ULP") Fixes: f3de19af0f5b ("Revert "net/tls: remove unused function tls_sw_sendpage_locked"") Signed-off-by: Willem de Bruijn willemb@google.com Acked-by: John Fastabend john.fastabend@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- include/net/tls.h | 2 ++ net/tls/tls_main.c | 1 + net/tls/tls_sw.c | 11 +++++++++++ 3 files changed, 14 insertions(+)
--- a/include/net/tls.h +++ b/include/net/tls.h @@ -364,6 +364,8 @@ int tls_set_sw_offload(struct sock *sk, void tls_sw_strparser_arm(struct sock *sk, struct tls_context *ctx); void tls_sw_strparser_done(struct tls_context *tls_ctx); int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size); +int tls_sw_sendpage_locked(struct sock *sk, struct page *page, + int offset, size_t size, int flags); int tls_sw_sendpage(struct sock *sk, struct page *page, int offset, size_t size, int flags); void tls_sw_cancel_work_tx(struct tls_context *tls_ctx); --- a/net/tls/tls_main.c +++ b/net/tls/tls_main.c @@ -852,6 +852,7 @@ static int __init tls_register(void) { tls_sw_proto_ops = inet_stream_ops; tls_sw_proto_ops.splice_read = tls_sw_splice_read; + tls_sw_proto_ops.sendpage_locked = tls_sw_sendpage_locked,
#ifdef CONFIG_TLS_DEVICE tls_device_init(); --- a/net/tls/tls_sw.c +++ b/net/tls/tls_sw.c @@ -1204,6 +1204,17 @@ sendpage_end: return copied ? copied : ret; }
+int tls_sw_sendpage_locked(struct sock *sk, struct page *page, + int offset, size_t size, int flags) +{ + if (flags & ~(MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL | + MSG_SENDPAGE_NOTLAST | MSG_SENDPAGE_NOPOLICY | + MSG_NO_SHARED_FRAGS)) + return -ENOTSUPP; + + return tls_sw_do_sendpage(sk, page, offset, size, flags); +} + int tls_sw_sendpage(struct sock *sk, struct page *page, int offset, size_t size, int flags) {
From: Hangbin Liu liuhangbin@gmail.com
[ Upstream commit 004b39427f945696db30abb2c4e1a3856ffff819 ]
Previously we will return directly if (!rt || !rt->fib6_nh.fib_nh_gw_family) in function rt6_probe(), but after commit cc3a86c802f0 ("ipv6: Change rt6_probe to take a fib6_nh"), the logic changed to return if there is fib_nh_gw_family.
Fixes: cc3a86c802f0 ("ipv6: Change rt6_probe to take a fib6_nh") Signed-off-by: Hangbin Liu liuhangbin@gmail.com Reviewed-by: David Ahern dsahern@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/ipv6/route.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -634,7 +634,7 @@ static void rt6_probe(struct fib6_nh *fi * Router Reachability Probe MUST be rate-limited * to no more than one per minute. */ - if (fib6_nh->fib_nh_gw_family) + if (!fib6_nh->fib_nh_gw_family) return;
nh_gw = &fib6_nh->fib_nh_gw6;
From: Ivan Khoronzhuk ivan.khoronzhuk@linaro.org
[ Upstream commit b5a0faa3572ac70bd374bd66190ac3ad4fddab20 ]
The taprio qdisc allows to set mqprio setting but only once. In case if mqprio settings are provided next time the error is returned as it's not allowed to change traffic class mapping in-flignt and that is normal. But if configuration is absolutely the same - no need to return error. It allows to provide same command couple times, changing only base time for instance, or changing only scheds maps, but leaving mqprio setting w/o modification. It more corresponds the message: "Changing the traffic mapping of a running schedule is not supported", so reject mqprio if it's really changed.
Also corrected TC_BITMASK + 1 for consistency, as proposed.
Fixes: a3d43c0d56f1 ("taprio: Add support adding an admin schedule") Reviewed-by: Vladimir Oltean olteanv@gmail.com Tested-by: Vladimir Oltean olteanv@gmail.com Acked-by: Vinicius Costa Gomes vinicius.gomes@intel.com Signed-off-by: Ivan Khoronzhuk ivan.khoronzhuk@linaro.org Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/sched/sch_taprio.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-)
--- a/net/sched/sch_taprio.c +++ b/net/sched/sch_taprio.c @@ -842,7 +842,7 @@ static int taprio_parse_mqprio_opt(struc }
/* Verify priority mapping uses valid tcs */ - for (i = 0; i < TC_BITMASK + 1; i++) { + for (i = 0; i <= TC_BITMASK; i++) { if (qopt->prio_tc_map[i] >= qopt->num_tc) { NL_SET_ERR_MSG(extack, "Invalid traffic class in priority to traffic class mapping"); return -EINVAL; @@ -1014,6 +1014,26 @@ static void setup_txtime(struct taprio_s } }
+static int taprio_mqprio_cmp(const struct net_device *dev, + const struct tc_mqprio_qopt *mqprio) +{ + int i; + + if (!mqprio || mqprio->num_tc != dev->num_tc) + return -1; + + for (i = 0; i < mqprio->num_tc; i++) + if (dev->tc_to_txq[i].count != mqprio->count[i] || + dev->tc_to_txq[i].offset != mqprio->offset[i]) + return -1; + + for (i = 0; i <= TC_BITMASK; i++) + if (dev->prio_tc_map[i] != mqprio->prio_tc_map[i]) + return -1; + + return 0; +} + static int taprio_change(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) { @@ -1065,6 +1085,10 @@ static int taprio_change(struct Qdisc *s admin = rcu_dereference(q->admin_sched); rcu_read_unlock();
+ /* no changes - no new mqprio settings */ + if (!taprio_mqprio_cmp(dev, mqprio)) + mqprio = NULL; + if (mqprio && (oper || admin)) { NL_SET_ERR_MSG(extack, "Changing the traffic mapping of a running schedule is not supported"); err = -ENOTSUPP; @@ -1132,7 +1156,7 @@ static int taprio_change(struct Qdisc *s mqprio->offset[i]);
/* Always use supplied priority mappings */ - for (i = 0; i < TC_BITMASK + 1; i++) + for (i = 0; i <= TC_BITMASK; i++) netdev_set_prio_tc_map(dev, i, mqprio->prio_tc_map[i]); }
From: Marcelo Ricardo Leitner marcelo.leitner@gmail.com
[ Upstream commit ca749bbb108c24a876014c804f9777c545be4d59 ]
Commit eec4844fae7c ("proc/sysctl: add shared variables for range check") did: - .extra2 = &two, + .extra2 = SYSCTL_ONE, here, which doesn't seem to be intentional, given the changelog. This patch restores it to the previous, as the value of 2 still makes sense (used in fib_multipath_hash()).
Fixes: eec4844fae7c ("proc/sysctl: add shared variables for range check") Cc: Matteo Croce mcroce@redhat.com Signed-off-by: Marcelo Ricardo Leitner marcelo.leitner@gmail.com Acked-by: Matteo Croce mcroce@redhat.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/ipv4/sysctl_net_ipv4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -1028,7 +1028,7 @@ static struct ctl_table ipv4_net_table[] .mode = 0644, .proc_handler = proc_fib_multipath_hash_policy, .extra1 = SYSCTL_ZERO, - .extra2 = SYSCTL_ONE, + .extra2 = &two, }, #endif {
From: Eli Cohen eli@mellanox.com
[ Upstream commit a86db2269fca8019074b720baf2e0a35cddac4e9 ]
Be sure to release the neighbour in case of failures after successful route lookup.
Fixes: 101f4de9dd52 ("net/mlx5e: Move TC tunnel offloading code to separate source file") Signed-off-by: Eli Cohen eli@mellanox.com Reviewed-by: Roi Dayan roid@mellanox.com Signed-off-by: Saeed Mahameed saeedm@mellanox.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c @@ -232,12 +232,15 @@ int mlx5e_tc_tun_create_header_ipv4(stru if (max_encap_size < ipv4_encap_size) { mlx5_core_warn(priv->mdev, "encap size %d too big, max supported is %d\n", ipv4_encap_size, max_encap_size); - return -EOPNOTSUPP; + err = -EOPNOTSUPP; + goto out; }
encap_header = kzalloc(ipv4_encap_size, GFP_KERNEL); - if (!encap_header) - return -ENOMEM; + if (!encap_header) { + err = -ENOMEM; + goto out; + }
/* used by mlx5e_detach_encap to lookup a neigh hash table * entry in the neigh hash table when a user deletes a rule @@ -348,12 +351,15 @@ int mlx5e_tc_tun_create_header_ipv6(stru if (max_encap_size < ipv6_encap_size) { mlx5_core_warn(priv->mdev, "encap size %d too big, max supported is %d\n", ipv6_encap_size, max_encap_size); - return -EOPNOTSUPP; + err = -EOPNOTSUPP; + goto out; }
encap_header = kzalloc(ipv6_encap_size, GFP_KERNEL); - if (!encap_header) - return -ENOMEM; + if (!encap_header) { + err = -ENOMEM; + goto out; + }
/* used by mlx5e_detach_encap to lookup a neigh hash table * entry in the neigh hash table when a user deletes a rule
From: Eran Ben Elisha eranbe@mellanox.com
[ Upstream commit 24960574505c49b102ca1dfa6bf109669bca2a66 ]
On some old Firmwares, connector type value was not supported, and value read from FW was 0. For those, driver used link mode in order to set connector type in link_ksetting.
After FW exposed the connector type, driver translated the value to ethtool definitions. However, as 0 is a valid value, before returning PORT_OTHER, driver run the check of link mode in order to maintain backward compatibility.
Cited patch added support to EXT mode. With both features (connector type and EXT link modes) ,if connector_type read from FW is 0 and EXT mode is set, driver mistakenly compare EXT link modes to non-EXT link mode. Fixed that by skipping this comparison if we are in EXT mode, as connector type value is valid in this scenario.
Fixes: 6a897372417e ("net/mlx5: ethtool, Add ethtool support for 50Gbps per lane link modes") Signed-off-by: Eran Ben Elisha eranbe@mellanox.com Reviewed-by: Aya Levin ayal@mellanox.com Signed-off-by: Saeed Mahameed saeedm@mellanox.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -708,9 +708,9 @@ static int get_fec_supported_advertised(
static void ptys2ethtool_supported_advertised_port(struct ethtool_link_ksettings *link_ksettings, u32 eth_proto_cap, - u8 connector_type) + u8 connector_type, bool ext) { - if (!connector_type || connector_type >= MLX5E_CONNECTOR_TYPE_NUMBER) { + if ((!connector_type && !ext) || connector_type >= MLX5E_CONNECTOR_TYPE_NUMBER) { if (eth_proto_cap & (MLX5E_PROT_MASK(MLX5E_10GBASE_CR) | MLX5E_PROT_MASK(MLX5E_10GBASE_SR) | MLX5E_PROT_MASK(MLX5E_40GBASE_CR4) @@ -842,9 +842,9 @@ static int ptys2connector_type[MLX5E_CON [MLX5E_PORT_OTHER] = PORT_OTHER, };
-static u8 get_connector_port(u32 eth_proto, u8 connector_type) +static u8 get_connector_port(u32 eth_proto, u8 connector_type, bool ext) { - if (connector_type && connector_type < MLX5E_CONNECTOR_TYPE_NUMBER) + if ((connector_type || ext) && connector_type < MLX5E_CONNECTOR_TYPE_NUMBER) return ptys2connector_type[connector_type];
if (eth_proto & @@ -945,9 +945,9 @@ int mlx5e_ethtool_get_link_ksettings(str eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap;
link_ksettings->base.port = get_connector_port(eth_proto_oper, - connector_type); + connector_type, ext); ptys2ethtool_supported_advertised_port(link_ksettings, eth_proto_admin, - connector_type); + connector_type, ext); get_lp_advertising(mdev, eth_proto_lp, link_ksettings);
if (an_status == MLX5_AN_COMPLETE)
From: Shani Shapp shanish@mellanox.com
[ Upstream commit b7eca940322f47fd30dafb70da04d193a0154090 ]
Add the upcoming ConnectX-6 LX device ID.
Fixes: 85327a9c4150 ("net/mlx5: Update the list of the PCI supported devices") Signed-off-by: Shani Shapp shanish@mellanox.com Reviewed-by: Eran Ben Elisha eranbe@mellanox.com Signed-off-by: Saeed Mahameed saeedm@mellanox.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/ethernet/mellanox/mlx5/core/main.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -1552,6 +1552,7 @@ static const struct pci_device_id mlx5_c { PCI_VDEVICE(MELLANOX, 0x101c), MLX5_PCI_DEV_IS_VF}, /* ConnectX-6 VF */ { PCI_VDEVICE(MELLANOX, 0x101d) }, /* ConnectX-6 Dx */ { PCI_VDEVICE(MELLANOX, 0x101e), MLX5_PCI_DEV_IS_VF}, /* ConnectX Family mlx5Gen Virtual Function */ + { PCI_VDEVICE(MELLANOX, 0x101f) }, /* ConnectX-6 LX */ { PCI_VDEVICE(MELLANOX, 0xa2d2) }, /* BlueField integrated ConnectX-5 network controller */ { PCI_VDEVICE(MELLANOX, 0xa2d3), MLX5_PCI_DEV_IS_VF}, /* BlueField integrated ConnectX-5 network controller VF */ { PCI_VDEVICE(MELLANOX, 0xa2d6) }, /* BlueField-2 integrated ConnectX-6 Dx network controller */
From: Stefano Garzarella sgarzare@redhat.com
commit 6dbd3e66e7785a2f055bf84d98de9b8fd31ff3f5 upstream.
If the packets to sent to the guest are bigger than the buffer available, we can split them, using multiple buffers and fixing the length in the packet header. This is safe since virtio-vsock supports only stream sockets.
Signed-off-by: Stefano Garzarella sgarzare@redhat.com Reviewed-by: Stefan Hajnoczi stefanha@redhat.com Acked-by: Michael S. Tsirkin mst@redhat.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/vhost/vsock.c | 66 +++++++++++++++++++++++--------- net/vmw_vsock/virtio_transport_common.c | 15 +++++-- 2 files changed, 60 insertions(+), 21 deletions(-)
--- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c @@ -102,7 +102,7 @@ vhost_transport_do_send_pkt(struct vhost struct iov_iter iov_iter; unsigned out, in; size_t nbytes; - size_t len; + size_t iov_len, payload_len; int head;
spin_lock_bh(&vsock->send_pkt_list_lock); @@ -147,8 +147,24 @@ vhost_transport_do_send_pkt(struct vhost break; }
- len = iov_length(&vq->iov[out], in); - iov_iter_init(&iov_iter, READ, &vq->iov[out], in, len); + iov_len = iov_length(&vq->iov[out], in); + if (iov_len < sizeof(pkt->hdr)) { + virtio_transport_free_pkt(pkt); + vq_err(vq, "Buffer len [%zu] too small\n", iov_len); + break; + } + + iov_iter_init(&iov_iter, READ, &vq->iov[out], in, iov_len); + payload_len = pkt->len - pkt->off; + + /* If the packet is greater than the space available in the + * buffer, we split it using multiple buffers. + */ + if (payload_len > iov_len - sizeof(pkt->hdr)) + payload_len = iov_len - sizeof(pkt->hdr); + + /* Set the correct length in the header */ + pkt->hdr.len = cpu_to_le32(payload_len);
nbytes = copy_to_iter(&pkt->hdr, sizeof(pkt->hdr), &iov_iter); if (nbytes != sizeof(pkt->hdr)) { @@ -157,33 +173,47 @@ vhost_transport_do_send_pkt(struct vhost break; }
- nbytes = copy_to_iter(pkt->buf, pkt->len, &iov_iter); - if (nbytes != pkt->len) { + nbytes = copy_to_iter(pkt->buf + pkt->off, payload_len, + &iov_iter); + if (nbytes != payload_len) { virtio_transport_free_pkt(pkt); vq_err(vq, "Faulted on copying pkt buf\n"); break; }
- vhost_add_used(vq, head, sizeof(pkt->hdr) + pkt->len); + vhost_add_used(vq, head, sizeof(pkt->hdr) + payload_len); added = true;
- if (pkt->reply) { - int val; - - val = atomic_dec_return(&vsock->queued_replies); - - /* Do we have resources to resume tx processing? */ - if (val + 1 == tx_vq->num) - restart_tx = true; - } - /* Deliver to monitoring devices all correctly transmitted * packets. */ virtio_transport_deliver_tap_pkt(pkt);
- total_len += pkt->len; - virtio_transport_free_pkt(pkt); + pkt->off += payload_len; + total_len += payload_len; + + /* If we didn't send all the payload we can requeue the packet + * to send it with the next available buffer. + */ + if (pkt->off < pkt->len) { + spin_lock_bh(&vsock->send_pkt_list_lock); + list_add(&pkt->list, &vsock->send_pkt_list); + spin_unlock_bh(&vsock->send_pkt_list_lock); + } else { + if (pkt->reply) { + int val; + + val = atomic_dec_return(&vsock->queued_replies); + + /* Do we have resources to resume tx + * processing? + */ + if (val + 1 == tx_vq->num) + restart_tx = true; + } + + virtio_transport_free_pkt(pkt); + } } while(likely(!vhost_exceeds_weight(vq, ++pkts, total_len))); if (added) vhost_signal(&vsock->dev, vq); --- a/net/vmw_vsock/virtio_transport_common.c +++ b/net/vmw_vsock/virtio_transport_common.c @@ -91,8 +91,17 @@ static struct sk_buff *virtio_transport_ struct virtio_vsock_pkt *pkt = opaque; struct af_vsockmon_hdr *hdr; struct sk_buff *skb; + size_t payload_len; + void *payload_buf;
- skb = alloc_skb(sizeof(*hdr) + sizeof(pkt->hdr) + pkt->len, + /* A packet could be split to fit the RX buffer, so we can retrieve + * the payload length from the header and the buffer pointer taking + * care of the offset in the original packet. + */ + payload_len = le32_to_cpu(pkt->hdr.len); + payload_buf = pkt->buf + pkt->off; + + skb = alloc_skb(sizeof(*hdr) + sizeof(pkt->hdr) + payload_len, GFP_ATOMIC); if (!skb) return NULL; @@ -132,8 +141,8 @@ static struct sk_buff *virtio_transport_
skb_put_data(skb, &pkt->hdr, sizeof(pkt->hdr));
- if (pkt->len) { - skb_put_data(skb, pkt->buf, pkt->len); + if (payload_len) { + skb_put_data(skb, payload_buf, payload_len); }
return skb;
From: Thierry Reding treding@nvidia.com
commit b0391479ae04dfcbd208b9571c375064caad9a57 upstream.
When converting milliseconds to microseconds in commit fffa6af94894 ("gpio: max77620: Use correct unit for debounce times") some ~1 ms gaps were introduced between the various ranges supported by the controller. Fix this by changing the start of each range to the value immediately following the end of the previous range. This way a debounce time of, say 8250 us will translate into 16 ms instead of returning an -EINVAL error.
Typically the debounce delay is only ever set through device tree and specified in milliseconds, so we can never really hit this issue because debounce times are always a multiple of 1000 us.
The only notable exception for this is drivers/mmc/host/mmc-spi.c where the CD GPIO is requested, which passes a 1 us debounce time. According to a comment preceeding that code this should actually be 1 ms (i.e. 1000 us).
Reported-by: Pavel Machek pavel@denx.de Signed-off-by: Thierry Reding treding@nvidia.com Acked-by: Pavel Machek pavel@denx.de Cc: stable@vger.kernel.org Signed-off-by: Bartosz Golaszewski bgolaszewski@baylibre.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/gpio/gpio-max77620.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/drivers/gpio/gpio-max77620.c +++ b/drivers/gpio/gpio-max77620.c @@ -192,13 +192,13 @@ static int max77620_gpio_set_debounce(st case 0: val = MAX77620_CNFG_GPIO_DBNC_None; break; - case 1000 ... 8000: + case 1 ... 8000: val = MAX77620_CNFG_GPIO_DBNC_8ms; break; - case 9000 ... 16000: + case 8001 ... 16000: val = MAX77620_CNFG_GPIO_DBNC_16ms; break; - case 17000 ... 32000: + case 16001 ... 32000: val = MAX77620_CNFG_GPIO_DBNC_32ms; break; default:
From: Thierry Reding treding@nvidia.com
commit f88c117b6d6d7e96557b6ee143b26b550fc51076 upstream.
The debounce time passed to gpiod_set_debounce() is specified in microseconds, so make sure to use the correct unit when computing the register values, which denote delays in milliseconds.
Signed-off-by: Thierry Reding treding@nvidia.com Cc: stable@vger.kernel.org Fixes: 18bc64b3aebf ("gpio: Initial support for ROHM bd70528 GPIO block") [Bartosz: fixed a typo in commit message] Signed-off-by: Bartosz Golaszewski bgolaszewski@baylibre.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/gpio/gpio-bd70528.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/drivers/gpio/gpio-bd70528.c +++ b/drivers/gpio/gpio-bd70528.c @@ -25,13 +25,13 @@ static int bd70528_set_debounce(struct b case 0: val = BD70528_DEBOUNCE_DISABLE; break; - case 1 ... 15: + case 1 ... 15000: val = BD70528_DEBOUNCE_15MS; break; - case 16 ... 30: + case 15001 ... 30000: val = BD70528_DEBOUNCE_30MS; break; - case 31 ... 50: + case 30001 ... 50000: val = BD70528_DEBOUNCE_50MS; break; default:
From: Laura Abbott labbott@redhat.com
commit 0161a94e2d1c713bd34d72bc0239d87c31747bf7 upstream.
gpio tools fail to build correctly with make parallelization:
$ make -s -j24 ld: gpio-utils.o: file not recognized: file truncated make[1]: *** [/home/labbott/linux_upstream/tools/build/Makefile.build:145: lsgpio-in.o] Error 1 make: *** [Makefile:43: lsgpio-in.o] Error 2 make: *** Waiting for unfinished jobs....
This is because gpio-utils.o is used across multiple targets. Fix this by making gpio-utios.o a proper dependency.
Cc: stable@vger.kernel.org Signed-off-by: Laura Abbott labbott@redhat.com Signed-off-by: Bartosz Golaszewski bgolaszewski@baylibre.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- tools/gpio/Build | 1 + tools/gpio/Makefile | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-)
--- a/tools/gpio/Build +++ b/tools/gpio/Build @@ -1,3 +1,4 @@ +gpio-utils-y += gpio-utils.o lsgpio-y += lsgpio.o gpio-utils.o gpio-hammer-y += gpio-hammer.o gpio-utils.o gpio-event-mon-y += gpio-event-mon.o gpio-utils.o --- a/tools/gpio/Makefile +++ b/tools/gpio/Makefile @@ -35,11 +35,15 @@ $(OUTPUT)include/linux/gpio.h: ../../inc
prepare: $(OUTPUT)include/linux/gpio.h
+GPIO_UTILS_IN := $(output)gpio-utils-in.o +$(GPIO_UTILS_IN): prepare FORCE + $(Q)$(MAKE) $(build)=gpio-utils + # # lsgpio # LSGPIO_IN := $(OUTPUT)lsgpio-in.o -$(LSGPIO_IN): prepare FORCE +$(LSGPIO_IN): prepare FORCE $(OUTPUT)gpio-utils-in.o $(Q)$(MAKE) $(build)=lsgpio $(OUTPUT)lsgpio: $(LSGPIO_IN) $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ @@ -48,7 +52,7 @@ $(OUTPUT)lsgpio: $(LSGPIO_IN) # gpio-hammer # GPIO_HAMMER_IN := $(OUTPUT)gpio-hammer-in.o -$(GPIO_HAMMER_IN): prepare FORCE +$(GPIO_HAMMER_IN): prepare FORCE $(OUTPUT)gpio-utils-in.o $(Q)$(MAKE) $(build)=gpio-hammer $(OUTPUT)gpio-hammer: $(GPIO_HAMMER_IN) $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ @@ -57,7 +61,7 @@ $(OUTPUT)gpio-hammer: $(GPIO_HAMMER_IN) # gpio-event-mon # GPIO_EVENT_MON_IN := $(OUTPUT)gpio-event-mon-in.o -$(GPIO_EVENT_MON_IN): prepare FORCE +$(GPIO_EVENT_MON_IN): prepare FORCE $(OUTPUT)gpio-utils-in.o $(Q)$(MAKE) $(build)=gpio-event-mon $(OUTPUT)gpio-event-mon: $(GPIO_EVENT_MON_IN) $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
From: Luc Van Oostenryck luc.vanoostenryck@gmail.com
commit 9e77716a75bc6cf54965e5ec069ba7c02b32251c upstream.
pidfd_poll() is defined as returning 'unsigned int' but the .poll method is declared as returning '__poll_t', a bitwise type.
Fix this by using the proper return type and using the EPOLL constants instead of the POLL ones, as required for __poll_t.
Fixes: b53b0b9d9a61 ("pidfd: add polling support") Cc: Joel Fernandes (Google) joel@joelfernandes.org Cc: stable@vger.kernel.org # 5.3 Signed-off-by: Luc Van Oostenryck luc.vanoostenryck@gmail.com Reviewed-by: Christian Brauner christian.brauner@ubuntu.com Link: https://lore.kernel.org/r/20191120003320.31138-1-luc.vanoostenryck@gmail.com Signed-off-by: Christian Brauner christian.brauner@ubuntu.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- kernel/fork.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/kernel/fork.c +++ b/kernel/fork.c @@ -1713,11 +1713,11 @@ static void pidfd_show_fdinfo(struct seq /* * Poll support for process exit notification. */ -static unsigned int pidfd_poll(struct file *file, struct poll_table_struct *pts) +static __poll_t pidfd_poll(struct file *file, struct poll_table_struct *pts) { struct task_struct *task; struct pid *pid = file->private_data; - int poll_flags = 0; + __poll_t poll_flags = 0;
poll_wait(file, &pid->wait_pidfd, pts);
@@ -1729,7 +1729,7 @@ static unsigned int pidfd_poll(struct fi * group, then poll(2) should block, similar to the wait(2) family. */ if (!task || (task->exit_state && thread_group_empty(task))) - poll_flags = POLLIN | POLLRDNORM; + poll_flags = EPOLLIN | EPOLLRDNORM; rcu_read_unlock();
return poll_flags;
From: Sun Ke sunke32@huawei.com
commit dff10bbea4be47bdb615b036c834a275b7c68133 upstream.
Before returning NULL, put the sock first.
Cc: stable@vger.kernel.org Fixes: cf1b2326b734 ("nbd: verify socket is supported during setup") Reviewed-by: Josef Bacik josef@toxicpanda.com Reviewed-by: Mike Christie mchristi@redhat.com Signed-off-by: Sun Ke sunke32@huawei.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/block/nbd.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -956,6 +956,7 @@ static struct socket *nbd_get_socket(str if (sock->ops->shutdown == sock_no_shutdown) { dev_err(disk_to_dev(nbd->disk), "Unsupported socket: shutdown callout must be supported.\n"); *err = -EINVAL; + sockfd_put(sock); return NULL; }
From: Laurent Vivier lvivier@redhat.com
commit d791cfcbf98191122af70b053a21075cb450d119 upstream.
When we hot unplug a virtserialport and then try to hot plug again, it fails:
(qemu) chardev-add socket,id=serial0,path=/tmp/serial0,server,nowait (qemu) device_add virtserialport,bus=virtio-serial0.0,nr=2,\ chardev=serial0,id=serial0,name=serial0 (qemu) device_del serial0 (qemu) device_add virtserialport,bus=virtio-serial0.0,nr=2,\ chardev=serial0,id=serial0,name=serial0 kernel error: virtio-ports vport2p2: Error allocating inbufs qemu error: virtio-serial-bus: Guest failure in adding port 2 for device \ virtio-serial0.0
This happens because buffers for the in_vq are allocated when the port is added but are not released when the port is unplugged.
They are only released when virtconsole is removed (see a7a69ec0d8e4)
To avoid the problem and to be symmetric, we could allocate all the buffers in init_vqs() as they are released in remove_vqs(), but it sounds like a waste of memory.
Rather than that, this patch changes add_port() logic to ignore ENOSPC error in fill_queue(), which means queue has already been filled.
Fixes: a7a69ec0d8e4 ("virtio_console: free buffers after reset") Cc: mst@redhat.com Cc: stable@vger.kernel.org Signed-off-by: Laurent Vivier lvivier@redhat.com Signed-off-by: Michael S. Tsirkin mst@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/char/virtio_console.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-)
--- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -1325,24 +1325,24 @@ static void set_console_size(struct port port->cons.ws.ws_col = cols; }
-static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock) +static int fill_queue(struct virtqueue *vq, spinlock_t *lock) { struct port_buffer *buf; - unsigned int nr_added_bufs; + int nr_added_bufs; int ret;
nr_added_bufs = 0; do { buf = alloc_buf(vq->vdev, PAGE_SIZE, 0); if (!buf) - break; + return -ENOMEM;
spin_lock_irq(lock); ret = add_inbuf(vq, buf); if (ret < 0) { spin_unlock_irq(lock); free_buf(buf, true); - break; + return ret; } nr_added_bufs++; spin_unlock_irq(lock); @@ -1362,7 +1362,6 @@ static int add_port(struct ports_device char debugfs_name[16]; struct port *port; dev_t devt; - unsigned int nr_added_bufs; int err;
port = kmalloc(sizeof(*port), GFP_KERNEL); @@ -1421,11 +1420,13 @@ static int add_port(struct ports_device spin_lock_init(&port->outvq_lock); init_waitqueue_head(&port->waitqueue);
- /* Fill the in_vq with buffers so the host can send us data. */ - nr_added_bufs = fill_queue(port->in_vq, &port->inbuf_lock); - if (!nr_added_bufs) { + /* We can safely ignore ENOSPC because it means + * the queue already has buffers. Buffers are removed + * only by virtcons_remove(), not by unplug_port() + */ + err = fill_queue(port->in_vq, &port->inbuf_lock); + if (err < 0 && err != -ENOSPC) { dev_err(port->dev, "Error allocating inbufs\n"); - err = -ENOMEM; goto free_device; }
@@ -2059,14 +2060,11 @@ static int virtcons_probe(struct virtio_ INIT_WORK(&portdev->control_work, &control_work_handler);
if (multiport) { - unsigned int nr_added_bufs; - spin_lock_init(&portdev->c_ivq_lock); spin_lock_init(&portdev->c_ovq_lock);
- nr_added_bufs = fill_queue(portdev->c_ivq, - &portdev->c_ivq_lock); - if (!nr_added_bufs) { + err = fill_queue(portdev->c_ivq, &portdev->c_ivq_lock); + if (err < 0) { dev_err(&vdev->dev, "Error allocating buffers for control queue\n"); /* @@ -2077,7 +2075,7 @@ static int virtcons_probe(struct virtio_ VIRTIO_CONSOLE_DEVICE_READY, 0); /* Device was functional: we need full cleanup. */ virtcons_remove(vdev); - return -ENOMEM; + return err; } } else { /*
From: Halil Pasic pasic@linux.ibm.com
commit f7728002c1c7bfa787b276a31c3ef458739b8e7c upstream.
Commit 780bc7903a32 ("virtio_ring: Support DMA APIs") makes virtqueue_add() return -EIO when we fail to map our I/O buffers. This is a very realistic scenario for guests with encrypted memory, as swiotlb may run out of space, depending on it's size and the I/O load.
The virtio-blk driver interprets -EIO form virtqueue_add() as an IO error, despite the fact that swiotlb full is in absence of bugs a recoverable condition.
Let us change the return code to -ENOMEM, and make the block layer recover form these failures when virtio-blk encounters the condition described above.
Cc: stable@vger.kernel.org Fixes: 780bc7903a32 ("virtio_ring: Support DMA APIs") Signed-off-by: Halil Pasic pasic@linux.ibm.com Tested-by: Michael Mueller mimu@linux.ibm.com Signed-off-by: Michael S. Tsirkin mst@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/virtio/virtio_ring.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -583,7 +583,7 @@ unmap_release: kfree(desc);
END_USE(vq); - return -EIO; + return -ENOMEM; }
static bool virtqueue_kick_prepare_split(struct virtqueue *_vq) @@ -1085,7 +1085,7 @@ unmap_release: kfree(desc);
END_USE(vq); - return -EIO; + return -ENOMEM; }
static inline int virtqueue_add_packed(struct virtqueue *_vq,
From: Wei Wang wei.w.wang@intel.com
commit c9a6820fc0da2603be3054ee7590eb9f350508a7 upstream.
Instead of multiplying by page order, virtio balloon divided by page order. The result is that it can return 0 if there are a bit less than MAX_ORDER - 1 pages in use, and then shrinker scan won't be called.
Cc: stable@vger.kernel.org Fixes: 71994620bb25 ("virtio_balloon: replace oom notifier with shrinker") Signed-off-by: Wei Wang wei.w.wang@intel.com Signed-off-by: Michael S. Tsirkin mst@redhat.com Reviewed-by: David Hildenbrand david@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/virtio/virtio_balloon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -820,7 +820,7 @@ static unsigned long virtio_balloon_shri unsigned long count;
count = vb->num_pages / VIRTIO_BALLOON_PAGES_PER_PAGE; - count += vb->num_free_page_blocks >> VIRTIO_BALLOON_FREE_PAGE_ORDER; + count += vb->num_free_page_blocks << VIRTIO_BALLOON_FREE_PAGE_ORDER;
return count; }
From: Joseph Qi joseph.qi@linux.alibaba.com
commit 94b07b6f9e2e996afff7395de6b35f34f4cb10bf upstream.
This reverts commit 56e94ea132bb5c2c1d0b60a6aeb34dcb7d71a53d.
Commit 56e94ea132bb ("fs: ocfs2: fix possible null-pointer dereferences in ocfs2_xa_prepare_entry()") introduces a regression that fail to create directory with mount option user_xattr and acl. Actually the reported NULL pointer dereference case can be correctly handled by loc->xl_ops->xlo_add_entry(), so revert it.
Link: http://lkml.kernel.org/r/1573624916-83825-1-git-send-email-joseph.qi@linux.a... Fixes: 56e94ea132bb ("fs: ocfs2: fix possible null-pointer dereferences in ocfs2_xa_prepare_entry()") Signed-off-by: Joseph Qi joseph.qi@linux.alibaba.com Reported-by: Thomas Voegtle tv@lio96.de Acked-by: Changwei Ge gechangwei@live.cn Cc: Jia-Ju Bai baijiaju1990@gmail.com Cc: Mark Fasheh mark@fasheh.com Cc: Joel Becker jlbec@evilplan.org Cc: Junxiao Bi junxiao.bi@oracle.com Cc: Gang He ghe@suse.com Cc: Jun Piao piaojun@huawei.com Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- fs/ocfs2/xattr.c | 56 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 23 deletions(-)
--- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -1490,6 +1490,18 @@ static int ocfs2_xa_check_space(struct o return loc->xl_ops->xlo_check_space(loc, xi); }
+static void ocfs2_xa_add_entry(struct ocfs2_xa_loc *loc, u32 name_hash) +{ + loc->xl_ops->xlo_add_entry(loc, name_hash); + loc->xl_entry->xe_name_hash = cpu_to_le32(name_hash); + /* + * We can't leave the new entry's xe_name_offset at zero or + * add_namevalue() will go nuts. We set it to the size of our + * storage so that it can never be less than any other entry. + */ + loc->xl_entry->xe_name_offset = cpu_to_le16(loc->xl_size); +} + static void ocfs2_xa_add_namevalue(struct ocfs2_xa_loc *loc, struct ocfs2_xattr_info *xi) { @@ -2121,31 +2133,29 @@ static int ocfs2_xa_prepare_entry(struct if (rc) goto out;
- if (!loc->xl_entry) { - rc = -EINVAL; - goto out; - } - - if (ocfs2_xa_can_reuse_entry(loc, xi)) { - orig_value_size = loc->xl_entry->xe_value_size; - rc = ocfs2_xa_reuse_entry(loc, xi, ctxt); - if (rc) - goto out; - goto alloc_value; - } + if (loc->xl_entry) { + if (ocfs2_xa_can_reuse_entry(loc, xi)) { + orig_value_size = loc->xl_entry->xe_value_size; + rc = ocfs2_xa_reuse_entry(loc, xi, ctxt); + if (rc) + goto out; + goto alloc_value; + }
- if (!ocfs2_xattr_is_local(loc->xl_entry)) { - orig_clusters = ocfs2_xa_value_clusters(loc); - rc = ocfs2_xa_value_truncate(loc, 0, ctxt); - if (rc) { - mlog_errno(rc); - ocfs2_xa_cleanup_value_truncate(loc, - "overwriting", - orig_clusters); - goto out; + if (!ocfs2_xattr_is_local(loc->xl_entry)) { + orig_clusters = ocfs2_xa_value_clusters(loc); + rc = ocfs2_xa_value_truncate(loc, 0, ctxt); + if (rc) { + mlog_errno(rc); + ocfs2_xa_cleanup_value_truncate(loc, + "overwriting", + orig_clusters); + goto out; + } } - } - ocfs2_xa_wipe_namevalue(loc); + ocfs2_xa_wipe_namevalue(loc); + } else + ocfs2_xa_add_entry(loc, name_hash);
/* * If we get here, we have a blank entry. Fill it. We grow our
From: Andrey Ryabinin aryabinin@virtuozzo.com
commit 9a63236f1ad82d71a98aa80320b6cb618fb32f44 upstream.
It's possible to hit the WARN_ON_ONCE(page_mapped(page)) in remove_stable_node() when it races with __mmput() and squeezes in between ksm_exit() and exit_mmap().
WARNING: CPU: 0 PID: 3295 at mm/ksm.c:888 remove_stable_node+0x10c/0x150
Call Trace: remove_all_stable_nodes+0x12b/0x330 run_store+0x4ef/0x7b0 kernfs_fop_write+0x200/0x420 vfs_write+0x154/0x450 ksys_write+0xf9/0x1d0 do_syscall_64+0x99/0x510 entry_SYSCALL_64_after_hwframe+0x49/0xbe
Remove the warning as there is nothing scary going on.
Link: http://lkml.kernel.org/r/20191119131850.5675-1-aryabinin@virtuozzo.com Fixes: cbf86cfe04a6 ("ksm: remove old stable nodes more thoroughly") Signed-off-by: Andrey Ryabinin aryabinin@virtuozzo.com Acked-by: Hugh Dickins hughd@google.com Cc: Andrea Arcangeli aarcange@redhat.com Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- mm/ksm.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
--- a/mm/ksm.c +++ b/mm/ksm.c @@ -885,13 +885,13 @@ static int remove_stable_node(struct sta return 0; }
- if (WARN_ON_ONCE(page_mapped(page))) { - /* - * This should not happen: but if it does, just refuse to let - * merge_across_nodes be switched - there is no need to panic. - */ - err = -EBUSY; - } else { + /* + * Page could be still mapped if this races with __mmput() running in + * between ksm_exit() and exit_mmap(). Just refuse to let + * merge_across_nodes/max_page_sharing be switched. + */ + err = -EBUSY; + if (!page_mapped(page)) { /* * The stable node did not yet appear stale to get_ksm_page(), * since that allows for an unmapped ksm page to be recognized
From: Alex Deucher alexander.deucher@amd.com
commit c57040d333c6729ce99c2cb95061045ff84c89ea upstream.
When gfxoff is enabled, accessing gfx registers via MMIO can lead to a hang.
Bug: https://bugzilla.kernel.org/show_bug.cgi?id=205497 Acked-by: Xiaojie Yuan xiaojie.yuan@amd.com Reviewed-by: Evan Quan evan.quan@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -635,15 +635,19 @@ static int amdgpu_info_ioctl(struct drm_ return -ENOMEM; alloc_size = info->read_mmr_reg.count * sizeof(*regs);
- for (i = 0; i < info->read_mmr_reg.count; i++) + amdgpu_gfx_off_ctrl(adev, false); + for (i = 0; i < info->read_mmr_reg.count; i++) { if (amdgpu_asic_read_register(adev, se_num, sh_num, info->read_mmr_reg.dword_offset + i, ®s[i])) { DRM_DEBUG_KMS("unallowed offset %#x\n", info->read_mmr_reg.dword_offset + i); kfree(regs); + amdgpu_gfx_off_ctrl(adev, true); return -EFAULT; } + } + amdgpu_gfx_off_ctrl(adev, true); n = copy_to_user(out, regs, min(size, alloc_size)); kfree(regs); return n ? -EFAULT : 0;
From: Alex Deucher alexander.deucher@amd.com
commit 941a0a7945c39f36a16634bc65c2649a1b94eee1 upstream.
There are still combinations of sbios and firmware that are not stable.
Bug: https://bugzilla.kernel.org/show_bug.cgi?id=204689 Acked-by: Christian König christian.koenig@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -596,8 +596,13 @@ static void gfx_v9_0_check_if_need_gfxof case CHIP_VEGA20: break; case CHIP_RAVEN: - if (!(adev->rev_id >= 0x8 || adev->pdev->device == 0x15d8) - &&((adev->gfx.rlc_fw_version != 106 && + /* Disable GFXOFF on original raven. There are combinations + * of sbios and platforms that are not stable. + */ + if (!(adev->rev_id >= 0x8 || adev->pdev->device == 0x15d8)) + adev->pm.pp_feature &= ~PP_GFXOFF_MASK; + else if (!(adev->rev_id >= 0x8 || adev->pdev->device == 0x15d8) + &&((adev->gfx.rlc_fw_version != 106 && adev->gfx.rlc_fw_version < 531) || (adev->gfx.rlc_fw_version == 53815) || (adev->gfx.rlc_feature_version < 1) ||
From: Evan Quan evan.quan@amd.com
commit 355d991cb6ff6ae76b5e28b8edae144124c730e4 upstream.
Otherwise, the error message prompted will confuse user.
Signed-off-by: Evan Quan evan.quan@amd.com Acked-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-)
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -3477,18 +3477,31 @@ static int smu7_get_pp_table_entry(struc
static int smu7_get_gpu_power(struct pp_hwmgr *hwmgr, u32 *query) { + struct amdgpu_device *adev = hwmgr->adev; int i; u32 tmp = 0;
if (!query) return -EINVAL;
- smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetCurrPkgPwr, 0); - tmp = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); - *query = tmp; + /* + * PPSMC_MSG_GetCurrPkgPwr is not supported on: + * - Hawaii + * - Bonaire + * - Fiji + * - Tonga + */ + if ((adev->asic_type != CHIP_HAWAII) && + (adev->asic_type != CHIP_BONAIRE) && + (adev->asic_type != CHIP_FIJI) && + (adev->asic_type != CHIP_TONGA)) { + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetCurrPkgPwr, 0); + tmp = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); + *query = tmp;
- if (tmp != 0) - return 0; + if (tmp != 0) + return 0; + }
smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PmStatusLogStart); cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
From: Ville Syrjälä ville.syrjala@linux.intel.com
commit 8ac495f624a42809000255955be406f6a8a74b55 upstream.
Make sure we have a crtc before probing its primary plane's max stride. Initially I thought we can't get this far without crtcs, but looks like we can via the dumb_create ioctl.
Not sure if we shouldn't disable dumb buffer support entirely when we have no crtcs, but that would require some amount of work as the only thing currently being checked is dev->driver->dumb_create which we'd have to convert to some device specific dynamic thing.
Cc: stable@vger.kernel.org Reported-by: Mika Kuoppala mika.kuoppala@linux.intel.com Fixes: aa5ca8b7421c ("drm/i915: Align dumb buffer stride to 4k to allow for gtt remapping") Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com Link: https://patchwork.freedesktop.org/patch/msgid/20191106172349.11987-1-ville.s... Reviewed-by: Chris Wilson chris@chris-wilson.co.uk (cherry picked from commit baea9ffe64200033499a4955f431e315bb807899) Signed-off-by: Joonas Lahtinen joonas.lahtinen@linux.intel.com (cherry picked from commit aeec766133f99d45aad60d650de50fb382104d95) Signed-off-by: Rodrigo Vivi rodrigo.vivi@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/gpu/drm/i915/display/intel_display.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2519,6 +2519,9 @@ u32 intel_plane_fb_max_stride(struct drm * the highest stride limits of them all. */ crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_A); + if (!crtc) + return 0; + plane = to_intel_plane(crtc->base.primary);
return plane->max_stride(plane, pixel_format, modifier,
From: Chris Wilson chris@chris-wilson.co.uk
commit add3eeed3683e2636ef524db48e1a678757c8e96 upstream.
We report "frequencies" (actual-frequency, requested-frequency) as the number of accumulated cycles so that the average frequency over that period may be determined by the user. This means the units we report to the user are Mcycles (or just M), not MHz.
Signed-off-by: Chris Wilson chris@chris-wilson.co.uk Cc: Tvrtko Ursulin tvrtko.ursulin@intel.com Cc: stable@vger.kernel.org Reviewed-by: Tvrtko Ursulin tvrtko.ursulin@intel.com Link: https://patchwork.freedesktop.org/patch/msgid/20191109105356.5273-1-chris@ch... (cherry picked from commit e88866ef02851c88fe95a4bb97820b94b4d46f36) Signed-off-by: Joonas Lahtinen joonas.lahtinen@linux.intel.com (cherry picked from commit a7d87b70d6da96c6772e50728c8b4e78e4cbfd55) Signed-off-by: Rodrigo Vivi rodrigo.vivi@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/gpu/drm/i915/i915_pmu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -833,8 +833,8 @@ create_event_attributes(struct drm_i915_ const char *name; const char *unit; } events[] = { - __event(I915_PMU_ACTUAL_FREQUENCY, "actual-frequency", "MHz"), - __event(I915_PMU_REQUESTED_FREQUENCY, "requested-frequency", "MHz"), + __event(I915_PMU_ACTUAL_FREQUENCY, "actual-frequency", "M"), + __event(I915_PMU_REQUESTED_FREQUENCY, "requested-frequency", "M"), __event(I915_PMU_INTERRUPTS, "interrupts", NULL), __event(I915_PMU_RC6_RESIDENCY, "rc6-residency", "ns"), };
From: Chris Wilson chris@chris-wilson.co.uk
commit 2d691aeca4aecbb8d0414a777a46981a8e142b05 upstream.
set_page_dirty says:
For pages with a mapping this should be done under the page lock for the benefit of asynchronous memory errors who prefer a consistent dirty state. This rule can be broken in some special cases, but should be better not to.
Under those rules, it is only safe for us to use the plain set_page_dirty calls for shmemfs/anonymous memory. Userptr may be used with real mappings and so needs to use the locked version (set_page_dirty_lock).
However, following a try_to_unmap() we may want to remove the userptr and so call put_pages(). However, try_to_unmap() acquires the page lock and so we must avoid recursively locking the pages ourselves -- which means that we cannot safely acquire the lock around set_page_dirty(). Since we can't be sure of the lock, we have to risk skip dirtying the page, or else risk calling set_page_dirty() without a lock and so risk fs corruption.
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=203317 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112012 Fixes: 5cc9ed4b9a7a ("drm/i915: Introduce mapping of user pages into video memory (userptr) ioctl") Signed-off-by: Chris Wilson chris@chris-wilson.co.uk Cc: Lionel Landwerlin lionel.g.landwerlin@intel.com Cc: Tvrtko Ursulin tvrtko.ursulin@intel.com Cc: Joonas Lahtinen joonas.lahtinen@linux.intel.com Cc: stable@vger.kernel.org Reviewed-by: Tvrtko Ursulin tvrtko.ursulin@intel.com Link: https://patchwork.freedesktop.org/patch/msgid/20191111133205.11590-1-chris@c... (cherry picked from commit 0d4bbe3d407f79438dc4f87943db21f7134cfc65) Signed-off-by: Joonas Lahtinen joonas.lahtinen@linux.intel.com (cherry picked from commit cee7fb437edcdb2f9f8affa959e274997f5dca4d) Signed-off-by: Rodrigo Vivi rodrigo.vivi@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c @@ -663,8 +663,28 @@ i915_gem_userptr_put_pages(struct drm_i9 i915_gem_gtt_finish_pages(obj, pages);
for_each_sgt_page(page, sgt_iter, pages) { - if (obj->mm.dirty) + if (obj->mm.dirty && trylock_page(page)) { + /* + * As this may not be anonymous memory (e.g. shmem) + * but exist on a real mapping, we have to lock + * the page in order to dirty it -- holding + * the page reference is not sufficient to + * prevent the inode from being truncated. + * Play safe and take the lock. + * + * However...! + * + * The mmu-notifier can be invalidated for a + * migrate_page, that is alreadying holding the lock + * on the page. Such a try_to_unmap() will result + * in us calling put_pages() and so recursively try + * to lock the page. We avoid that deadlock with + * a trylock_page() and in exchange we risk missing + * some page dirtying. + */ set_page_dirty(page); + unlock_page(page); + }
mark_page_accessed(page); put_page(page);
From: Tomas Bortoli tomasbortoli@gmail.com
commit cf94da6f502d8caecabd56b194541c873c8a7a3c upstream.
Syzbot reported an invalid-free that I introduced fixing a memleak.
bcsp_recv() also frees bcsp->rx_skb but never nullifies its value. Nullify bcsp->rx_skb every time it is freed.
Signed-off-by: Tomas Bortoli tomasbortoli@gmail.com Reported-by: syzbot+a0d209a4676664613e76@syzkaller.appspotmail.com Signed-off-by: Marcel Holtmann marcel@holtmann.org Cc: Alexander Potapenko glider@google.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/bluetooth/hci_bcsp.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/drivers/bluetooth/hci_bcsp.c +++ b/drivers/bluetooth/hci_bcsp.c @@ -591,6 +591,7 @@ static int bcsp_recv(struct hci_uart *hu if (*ptr == 0xc0) { BT_ERR("Short BCSP packet"); kfree_skb(bcsp->rx_skb); + bcsp->rx_skb = NULL; bcsp->rx_state = BCSP_W4_PKT_START; bcsp->rx_count = 0; } else @@ -606,6 +607,7 @@ static int bcsp_recv(struct hci_uart *hu bcsp->rx_skb->data[2])) != bcsp->rx_skb->data[3]) { BT_ERR("Error in BCSP hdr checksum"); kfree_skb(bcsp->rx_skb); + bcsp->rx_skb = NULL; bcsp->rx_state = BCSP_W4_PKT_DELIMITER; bcsp->rx_count = 0; continue; @@ -630,6 +632,7 @@ static int bcsp_recv(struct hci_uart *hu bscp_get_crc(bcsp));
kfree_skb(bcsp->rx_skb); + bcsp->rx_skb = NULL; bcsp->rx_state = BCSP_W4_PKT_DELIMITER; bcsp->rx_count = 0; continue;
From: Christian Lamparter chunkeey@gmail.com
commit f8914a14623a79b73f72b2b1ee4cd9b2cb91b735 upstream.
This patch restores the old behavior that read the chip_id on the QCA988x before resetting the chip. This needs to be done in this order since the unsupported QCA988x AR1A chips fall off the bus when resetted. Otherwise the next MMIO Op after the reset causes a BUS ERROR and panic.
Cc: stable@vger.kernel.org Fixes: 1a7fecb766c8 ("ath10k: reset chip before reading chip_id in probe") Signed-off-by: Christian Lamparter chunkeey@gmail.com Signed-off-by: Kalle Valo kvalo@codeaurora.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/net/wireless/ath/ath10k/pci.c | 36 +++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-)
--- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -3490,7 +3490,7 @@ static int ath10k_pci_probe(struct pci_d struct ath10k_pci *ar_pci; enum ath10k_hw_rev hw_rev; struct ath10k_bus_params bus_params = {}; - bool pci_ps; + bool pci_ps, is_qca988x = false; int (*pci_soft_reset)(struct ath10k *ar); int (*pci_hard_reset)(struct ath10k *ar); u32 (*targ_cpu_to_ce_addr)(struct ath10k *ar, u32 addr); @@ -3500,6 +3500,7 @@ static int ath10k_pci_probe(struct pci_d case QCA988X_2_0_DEVICE_ID: hw_rev = ATH10K_HW_QCA988X; pci_ps = false; + is_qca988x = true; pci_soft_reset = ath10k_pci_warm_reset; pci_hard_reset = ath10k_pci_qca988x_chip_reset; targ_cpu_to_ce_addr = ath10k_pci_qca988x_targ_cpu_to_ce_addr; @@ -3619,25 +3620,34 @@ static int ath10k_pci_probe(struct pci_d goto err_deinit_irq; }
+ bus_params.dev_type = ATH10K_DEV_TYPE_LL; + bus_params.link_can_suspend = true; + /* Read CHIP_ID before reset to catch QCA9880-AR1A v1 devices that + * fall off the bus during chip_reset. These chips have the same pci + * device id as the QCA9880 BR4A or 2R4E. So that's why the check. + */ + if (is_qca988x) { + bus_params.chip_id = + ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS); + if (bus_params.chip_id != 0xffffffff) { + if (!ath10k_pci_chip_is_supported(pdev->device, + bus_params.chip_id)) + goto err_unsupported; + } + } + ret = ath10k_pci_chip_reset(ar); if (ret) { ath10k_err(ar, "failed to reset chip: %d\n", ret); goto err_free_irq; }
- bus_params.dev_type = ATH10K_DEV_TYPE_LL; - bus_params.link_can_suspend = true; bus_params.chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS); - if (bus_params.chip_id == 0xffffffff) { - ath10k_err(ar, "failed to get chip id\n"); - goto err_free_irq; - } + if (bus_params.chip_id == 0xffffffff) + goto err_unsupported;
- if (!ath10k_pci_chip_is_supported(pdev->device, bus_params.chip_id)) { - ath10k_err(ar, "device %04x with chip_id %08x isn't supported\n", - pdev->device, bus_params.chip_id); + if (!ath10k_pci_chip_is_supported(pdev->device, bus_params.chip_id)) goto err_free_irq; - }
ret = ath10k_core_register(ar, &bus_params); if (ret) { @@ -3647,6 +3657,10 @@ static int ath10k_pci_probe(struct pci_d
return 0;
+err_unsupported: + ath10k_err(ar, "device %04x with chip_id %08x isn't supported\n", + pdev->device, bus_params.chip_id); + err_free_irq: ath10k_pci_free_irq(ar); ath10k_pci_rx_retry_sync(ar);
From: Bjorn Andersson bjorn.andersson@linaro.org
commit 7165ef890a4c44cf16db66b82fd78448f4bde6ba upstream.
The introduction of 768ec4c012ac ("ath10k: update HOST capability QMI message") served the purpose of supporting the new and extended HOST capability QMI message.
But while the new message adds a slew of optional members it changes the data type of the "daemon_support" member, which means that older versions of the firmware will fail to decode the incoming request message.
There is no way to detect this breakage from Linux and there's no way to recover from sending the wrong message (i.e. we can't just try one format and then fallback to the other), so a quirk is introduced in DeviceTree to indicate to the driver that the firmware requires the 8bit version of this message.
Cc: stable@vger.kernel.org Fixes: 768ec4c012ac ("ath10k: update HOST capability qmi message") Signed-off-by: Bjorn Andersson bjorn.andersson@linaro.org Acked-by: Rob Herring robh@kernel.org Signed-off-by: Kalle Valo kvalo@codeaurora.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt | 6 ++ drivers/net/wireless/ath/ath10k/qmi.c | 13 ++++- drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c | 22 ++++++++++ drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h | 1 drivers/net/wireless/ath/ath10k/snoc.c | 11 +++++ drivers/net/wireless/ath/ath10k/snoc.h | 1 6 files changed, 51 insertions(+), 3 deletions(-)
--- a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt +++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt @@ -81,6 +81,12 @@ Optional properties: Definition: Name of external front end module used. Some valid FEM names for example: "microsemi-lx5586", "sky85703-11" and "sky85803" etc. +- qcom,snoc-host-cap-8bit-quirk: + Usage: Optional + Value type: <empty> + Definition: Quirk specifying that the firmware expects the 8bit version + of the host capability QMI request +
Example (to supply PCI based wifi block details):
--- a/drivers/net/wireless/ath/ath10k/qmi.c +++ b/drivers/net/wireless/ath/ath10k/qmi.c @@ -581,22 +581,29 @@ static int ath10k_qmi_host_cap_send_sync { struct wlfw_host_cap_resp_msg_v01 resp = {}; struct wlfw_host_cap_req_msg_v01 req = {}; + struct qmi_elem_info *req_ei; struct ath10k *ar = qmi->ar; + struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); struct qmi_txn txn; int ret;
req.daemon_support_valid = 1; req.daemon_support = 0;
- ret = qmi_txn_init(&qmi->qmi_hdl, &txn, - wlfw_host_cap_resp_msg_v01_ei, &resp); + ret = qmi_txn_init(&qmi->qmi_hdl, &txn, wlfw_host_cap_resp_msg_v01_ei, + &resp); if (ret < 0) goto out;
+ if (test_bit(ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK, &ar_snoc->flags)) + req_ei = wlfw_host_cap_8bit_req_msg_v01_ei; + else + req_ei = wlfw_host_cap_req_msg_v01_ei; + ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn, QMI_WLFW_HOST_CAP_REQ_V01, WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN, - wlfw_host_cap_req_msg_v01_ei, &req); + req_ei, &req); if (ret < 0) { qmi_txn_cancel(&txn); ath10k_err(ar, "failed to send host capability request: %d\n", ret); --- a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c +++ b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c @@ -1988,6 +1988,28 @@ struct qmi_elem_info wlfw_host_cap_req_m {} };
+struct qmi_elem_info wlfw_host_cap_8bit_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + daemon_support_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + daemon_support), + }, + {} +}; + struct qmi_elem_info wlfw_host_cap_resp_msg_v01_ei[] = { { .data_type = QMI_STRUCT, --- a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h +++ b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h @@ -575,6 +575,7 @@ struct wlfw_host_cap_req_msg_v01 {
#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 189 extern struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[]; +extern struct qmi_elem_info wlfw_host_cap_8bit_req_msg_v01_ei[];
struct wlfw_host_cap_resp_msg_v01 { struct qmi_response_type_v01 resp; --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -1261,6 +1261,15 @@ out: return ret; }
+static void ath10k_snoc_quirks_init(struct ath10k *ar) +{ + struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); + struct device *dev = &ar_snoc->dev->dev; + + if (of_property_read_bool(dev->of_node, "qcom,snoc-host-cap-8bit-quirk")) + set_bit(ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK, &ar_snoc->flags); +} + int ath10k_snoc_fw_indication(struct ath10k *ar, u64 type) { struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); @@ -1678,6 +1687,8 @@ static int ath10k_snoc_probe(struct plat ar->ce_priv = &ar_snoc->ce; msa_size = drv_data->msa_size;
+ ath10k_snoc_quirks_init(ar); + ret = ath10k_snoc_resource_init(ar); if (ret) { ath10k_warn(ar, "failed to initialize resource: %d\n", ret); --- a/drivers/net/wireless/ath/ath10k/snoc.h +++ b/drivers/net/wireless/ath/ath10k/snoc.h @@ -63,6 +63,7 @@ enum ath10k_snoc_flags { ATH10K_SNOC_FLAG_REGISTERED, ATH10K_SNOC_FLAG_UNREGISTERING, ATH10K_SNOC_FLAG_RECOVERY, + ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK, };
struct ath10k_snoc {
From: Hui Peng benquike@gmail.com
commit bfd6e6e6c5d2ee43a3d9902b36e01fc7527ebb27 upstream.
The `ar_usb` field of `ath10k_usb_pipe_usb_pipe` objects are initialized to point to the containing `ath10k_usb` object according to endpoint descriptors read from the device side, as shown below in `ath10k_usb_setup_pipe_resources`:
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc;
// get the address from endpoint descriptor pipe_num = ath10k_usb_get_logical_pipe_num(ar_usb, endpoint->bEndpointAddress, &urbcount); ...... // select the pipe object pipe = &ar_usb->pipes[pipe_num];
// initialize the ar_usb field pipe->ar_usb = ar_usb; }
The driver assumes that the addresses reported in endpoint descriptors from device side to be complete. If a device is malicious and does not report complete addresses, it may trigger NULL-ptr-deref `ath10k_usb_alloc_urb_from_pipe` and `ath10k_usb_free_urb_to_pipe`.
This patch fixes the bug by preventing potential NULL-ptr-deref.
Signed-off-by: Hui Peng benquike@gmail.com Reported-by: Hui Peng benquike@gmail.com Reported-by: Mathias Payer mathias.payer@nebelwelt.net Reviewed-by: Greg Kroah-Hartman gregkh@linuxfoundation.org [groeck: Add driver tag to subject, fix build warning] Signed-off-by: Guenter Roeck linux@roeck-us.net Signed-off-by: Kalle Valo kvalo@codeaurora.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/net/wireless/ath/ath10k/usb.c | 8 ++++++++ 1 file changed, 8 insertions(+)
--- a/drivers/net/wireless/ath/ath10k/usb.c +++ b/drivers/net/wireless/ath/ath10k/usb.c @@ -38,6 +38,10 @@ ath10k_usb_alloc_urb_from_pipe(struct at struct ath10k_urb_context *urb_context = NULL; unsigned long flags;
+ /* bail if this pipe is not initialized */ + if (!pipe->ar_usb) + return NULL; + spin_lock_irqsave(&pipe->ar_usb->cs_lock, flags); if (!list_empty(&pipe->urb_list_head)) { urb_context = list_first_entry(&pipe->urb_list_head, @@ -55,6 +59,10 @@ static void ath10k_usb_free_urb_to_pipe( { unsigned long flags;
+ /* bail if this pipe is not initialized */ + if (!pipe->ar_usb) + return; + spin_lock_irqsave(&pipe->ar_usb->cs_lock, flags);
pipe->urb_cnt++;
From: Denis Efremov efremov@linux.com
commit 80e84f36412e0c5172447b6947068dca0d04ee82 upstream.
Currently, data variable in ar9003_hw_thermo_cal_apply() could be uninitialized if ar9300_otp_read_word() will fail to read the value. Initialize data variable with 0 to prevent an undefined behavior. This will be enough to handle error case when ar9300_otp_read_word() fails.
Fixes: 80fe43f2bbd5 ("ath9k_hw: Read and configure thermocal for AR9462") Cc: Rajkumar Manoharan rmanohar@qca.qualcomm.com Cc: John W. Linville linville@tuxdriver.com Cc: Kalle Valo kvalo@codeaurora.org Cc: "David S. Miller" davem@davemloft.net Cc: stable@vger.kernel.org Signed-off-by: Denis Efremov efremov@linux.com Signed-off-by: Kalle Valo kvalo@codeaurora.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -4183,7 +4183,7 @@ static void ar9003_hw_thermometer_apply(
static void ar9003_hw_thermo_cal_apply(struct ath_hw *ah) { - u32 data, ko, kg; + u32 data = 0, ko, kg;
if (!AR_SREV_9462_20_OR_LATER(ah)) return;
From: Adam Ford aford173@gmail.com
commit cef456cd354ef485f12d57000c455e83e416a2b6 upstream.
As nice as it would be to update firmware faster, that patch broke at least two different boards, an OMAP4+WL1285 based Motorola Droid 4, as reported by Sebasian Reichel and the Logic PD i.MX6Q + WL1837MOD.
This reverts commit a2e02f38eff84f199c8e32359eb213f81f270047.
Signed-off-by: Adam Ford aford173@gmail.com Acked-by: Sebastian Reichel sebastian.reichel@collabora.com Cc: stable@vger.kernel.org Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/bluetooth/hci_ll.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-)
--- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -621,13 +621,6 @@ static int ll_setup(struct hci_uart *hu)
serdev_device_set_flow_control(serdev, true);
- if (hu->oper_speed) - speed = hu->oper_speed; - else if (hu->proto->oper_speed) - speed = hu->proto->oper_speed; - else - speed = 0; - do { /* Reset the Bluetooth device */ gpiod_set_value_cansleep(lldev->enable_gpio, 0); @@ -639,20 +632,6 @@ static int ll_setup(struct hci_uart *hu) return err; }
- if (speed) { - __le32 speed_le = cpu_to_le32(speed); - struct sk_buff *skb; - - skb = __hci_cmd_sync(hu->hdev, - HCI_VS_UPDATE_UART_HCI_BAUDRATE, - sizeof(speed_le), &speed_le, - HCI_INIT_TIMEOUT); - if (!IS_ERR(skb)) { - kfree_skb(skb); - serdev_device_set_baudrate(serdev, speed); - } - } - err = download_firmware(lldev); if (!err) break; @@ -677,7 +656,25 @@ static int ll_setup(struct hci_uart *hu) }
/* Operational speed if any */ + if (hu->oper_speed) + speed = hu->oper_speed; + else if (hu->proto->oper_speed) + speed = hu->proto->oper_speed; + else + speed = 0;
+ if (speed) { + __le32 speed_le = cpu_to_le32(speed); + struct sk_buff *skb; + + skb = __hci_cmd_sync(hu->hdev, HCI_VS_UPDATE_UART_HCI_BAUDRATE, + sizeof(speed_le), &speed_le, + HCI_INIT_TIMEOUT); + if (!IS_ERR(skb)) { + kfree_skb(skb); + serdev_device_set_baudrate(serdev, speed); + } + }
return 0; }
From: Mike Snitzer snitzer@redhat.com
commit f612b2132db529feac4f965f28a1b9258ea7c22b upstream.
This reverts commit a1b89132dc4f61071bdeaab92ea958e0953380a1.
Revert required hand-patching due to subsequent changes that were applied since commit a1b89132dc4f61071bdeaab92ea958e0953380a1.
Requires: ed0302e83098d ("dm crypt: make workqueue names device-specific") Cc: stable@vger.kernel.org Bug: https://bugzilla.kernel.org/show_bug.cgi?id=199857 Reported-by: Vito Caputo vcaputo@pengaru.com Signed-off-by: Mike Snitzer snitzer@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/md/dm-crypt.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
--- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -2911,21 +2911,18 @@ static int crypt_ctr(struct dm_target *t }
ret = -ENOMEM; - cc->io_queue = alloc_workqueue("kcryptd_io/%s", - WQ_HIGHPRI | WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM, - 1, devname); + cc->io_queue = alloc_workqueue("kcryptd_io/%s", WQ_MEM_RECLAIM, 1, devname); if (!cc->io_queue) { ti->error = "Couldn't create kcryptd io queue"; goto bad; }
if (test_bit(DM_CRYPT_SAME_CPU, &cc->flags)) - cc->crypt_queue = alloc_workqueue("kcryptd/%s", - WQ_HIGHPRI | WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM, + cc->crypt_queue = alloc_workqueue("kcryptd/%s", WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM, 1, devname); else cc->crypt_queue = alloc_workqueue("kcryptd/%s", - WQ_HIGHPRI | WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM | WQ_UNBOUND, + WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM | WQ_UNBOUND, num_online_cpus(), devname); if (!cc->crypt_queue) { ti->error = "Couldn't create kcryptd queue";
From: John Pittman jpittman@redhat.com
commit 45422b704db392a6d79d07ee3e3670b11048bd53 upstream.
Due to unneeded multiplication in the out_free_pages portion of r10buf_pool_alloc(), when using a 3-copy raid10 layout, it is possible to access a resync_pages offset that has not been initialized. This access translates into a crash of the system within resync_free_pages() while passing a bad pointer to put_page(). Remove the multiplication, preventing access to the uninitialized area.
Fixes: f0250618361db ("md: raid10: don't use bio's vec table to manage resync pages") Cc: stable@vger.kernel.org # 4.12+ Signed-off-by: John Pittman jpittman@redhat.com Suggested-by: David Jeffery djeffery@redhat.com Reviewed-by: Laurence Oberman loberman@redhat.com Signed-off-by: Song Liu songliubraving@fb.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/md/raid10.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -191,7 +191,7 @@ static void * r10buf_pool_alloc(gfp_t gf
out_free_pages: while (--j >= 0) - resync_free_pages(&rps[j * 2]); + resync_free_pages(&rps[j]);
j = 0; out_free_bio:
From: Geert Uytterhoeven geert+renesas@glider.be
commit 6e4ff1c94a0477598ddbe4da47530aecdb4f7dff upstream.
Commit 1d4639567d97 ("mdio_bus: Fix PTR_ERR applied after initialization to constant") accidentally changed a check from -ENOTSUPP to -ENOSYS, causing failures if reset controller support is not enabled. E.g. on r7s72100/rskrza1:
sh-eth e8203000.ethernet: MDIO init failed: -524 sh-eth: probe of e8203000.ethernet failed with error -524
Seen on r8a7740/armadillo, r7s72100/rskrza1, and r7s9210/rza2mevb.
Fixes: 1d4639567d97 ("mdio_bus: Fix PTR_ERR applied after initialization to constant") Signed-off-by: Geert Uytterhoeven geert+renesas@glider.be Cc: YueHaibing yuehaibing@huawei.com Cc: David S. Miller davem@davemloft.net Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: David S. Miller davem@davemloft.net Cc: Marek Behún marek.behun@nic.cz Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/net/phy/mdio_bus.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
--- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -68,11 +68,12 @@ static int mdiobus_register_reset(struct if (mdiodev->dev.of_node) reset = devm_reset_control_get_exclusive(&mdiodev->dev, "phy"); - if (PTR_ERR(reset) == -ENOENT || - PTR_ERR(reset) == -ENOTSUPP) - reset = NULL; - else if (IS_ERR(reset)) - return PTR_ERR(reset); + if (IS_ERR(reset)) { + if (PTR_ERR(reset) == -ENOENT || PTR_ERR(reset) == -ENOTSUPP) + reset = NULL; + else + return PTR_ERR(reset); + }
mdiodev->reset_ctrl = reset;
From: Chester Lin clin@suse.com
commit 1d31999cf04c21709f72ceb17e65b54a401330da upstream.
adjust_lowmem_bounds() checks every memblocks in order to find the boundary between lowmem and highmem. However some memblocks could be marked as NOMAP so they are not used by kernel, which should be skipped while calculating the boundary.
Signed-off-by: Chester Lin clin@suse.com Reviewed-by: Mike Rapoport rppt@linux.ibm.com Signed-off-by: Russell King rmk+kernel@armlinux.org.uk Signed-off-by: Lee Jones lee.jones@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/arm/mm/mmu.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -1197,6 +1197,9 @@ void __init adjust_lowmem_bounds(void) phys_addr_t block_start = reg->base; phys_addr_t block_end = reg->base + reg->size;
+ if (memblock_is_nomap(reg)) + continue; + if (reg->base < vmalloc_limit) { if (block_end > lowmem_limit) /*
From: Alexander Kapshuk alexander.kapshuk@gmail.com
commit 700c1018b86d0d4b3f1f2d459708c0cdf42b521d upstream.
gawk 5.0.1 generates the following regexp warnings:
GEN /home/sasha/torvalds/tools/objtool/arch/x86/lib/inat-tables.c awk: ../arch/x86/tools/gen-insn-attr-x86.awk:260: warning: regexp escape sequence `:' is not a known regexp operator awk: ../arch/x86/tools/gen-insn-attr-x86.awk:350: (FILENAME=../arch/x86/lib/x86-opcode-map.txt FNR=41) warning: regexp escape sequence `&' is not a known regexp operator
Ealier versions of gawk are not known to generate these warnings. The gawk manual referenced below does not list characters ':' and '&' as needing escaping, so 'unescape' them. See
https://www.gnu.org/software/gawk/manual/html_node/Escape-Sequences.html
for more info.
Running diff on the output generated by the script before and after applying the patch reported no differences.
[ bp: Massage commit message. ]
[ Caught the respective tools header discrepancy. ] Reported-by: kbuild test robot lkp@intel.com Signed-off-by: Alexander Kapshuk alexander.kapshuk@gmail.com Signed-off-by: Borislav Petkov bp@suse.de Acked-by: Masami Hiramatsu mhiramat@kernel.org Cc: "H. Peter Anvin" hpa@zytor.com Cc: "Peter Zijlstra (Intel)" peterz@infradead.org Cc: Arnaldo Carvalho de Melo acme@redhat.com Cc: Ingo Molnar mingo@redhat.com Cc: Josh Poimboeuf jpoimboe@redhat.com Cc: Thomas Gleixner tglx@linutronix.de Cc: x86-ml x86@kernel.org Link: https://lkml.kernel.org/r/20190924044659.3785-1-alexander.kapshuk@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/x86/tools/gen-insn-attr-x86.awk | 4 ++-- tools/objtool/arch/x86/tools/gen-insn-attr-x86.awk | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)
--- a/arch/x86/tools/gen-insn-attr-x86.awk +++ b/arch/x86/tools/gen-insn-attr-x86.awk @@ -69,7 +69,7 @@ BEGIN {
lprefix1_expr = "\((66|!F3)\)" lprefix2_expr = "\(F3\)" - lprefix3_expr = "\((F2|!F3|66\&F2)\)" + lprefix3_expr = "\((F2|!F3|66&F2)\)" lprefix_expr = "\((66|F2|F3)\)" max_lprefix = 4
@@ -257,7 +257,7 @@ function convert_operands(count,opnd, return add_flags(imm, mod) }
-/^[0-9a-f]+:/ { +/^[0-9a-f]+:/ { if (NR == 1) next # get index --- a/tools/objtool/arch/x86/tools/gen-insn-attr-x86.awk +++ b/tools/objtool/arch/x86/tools/gen-insn-attr-x86.awk @@ -69,7 +69,7 @@ BEGIN {
lprefix1_expr = "\((66|!F3)\)" lprefix2_expr = "\(F3\)" - lprefix3_expr = "\((F2|!F3|66\&F2)\)" + lprefix3_expr = "\((F2|!F3|66&F2)\)" lprefix_expr = "\((66|F2|F3)\)" max_lprefix = 4
@@ -257,7 +257,7 @@ function convert_operands(count,opnd, return add_flags(imm, mod) }
-/^[0-9a-f]+:/ { +/^[0-9a-f]+:/ { if (NR == 1) next # get index
From: Waiman Long longman@redhat.com
commit 64870ed1b12e235cfca3f6c6da75b542c973ff78 upstream.
For MDS vulnerable processors with TSX support, enabling either MDS or TAA mitigations will enable the use of VERW to flush internal processor buffers at the right code path. IOW, they are either both mitigated or both not. However, if the command line options are inconsistent, the vulnerabilites sysfs files may not report the mitigation status correctly.
For example, with only the "mds=off" option:
vulnerabilities/mds:Vulnerable; SMT vulnerable vulnerabilities/tsx_async_abort:Mitigation: Clear CPU buffers; SMT vulnerable
The mds vulnerabilities file has wrong status in this case. Similarly, the taa vulnerability file will be wrong with mds mitigation on, but taa off.
Change taa_select_mitigation() to sync up the two mitigation status and have them turned off if both "mds=off" and "tsx_async_abort=off" are present.
Update documentation to emphasize the fact that both "mds=off" and "tsx_async_abort=off" have to be specified together for processors that are affected by both TAA and MDS to be effective.
[ bp: Massage and add kernel-parameters.txt change too. ]
Fixes: 1b42f017415b ("x86/speculation/taa: Add mitigation for TSX Async Abort") Signed-off-by: Waiman Long longman@redhat.com Signed-off-by: Borislav Petkov bp@suse.de Cc: Greg Kroah-Hartman gregkh@linuxfoundation.org Cc: "H. Peter Anvin" hpa@zytor.com Cc: Ingo Molnar mingo@redhat.com Cc: Jiri Kosina jkosina@suse.cz Cc: Jonathan Corbet corbet@lwn.net Cc: Josh Poimboeuf jpoimboe@redhat.com Cc: linux-doc@vger.kernel.org Cc: Mark Gross mgross@linux.intel.com Cc: stable@vger.kernel.org Cc: Pawan Gupta pawan.kumar.gupta@linux.intel.com Cc: Peter Zijlstra peterz@infradead.org Cc: Thomas Gleixner tglx@linutronix.de Cc: Tim Chen tim.c.chen@linux.intel.com Cc: Tony Luck tony.luck@intel.com Cc: Tyler Hicks tyhicks@canonical.com Cc: x86-ml x86@kernel.org Link: https://lkml.kernel.org/r/20191115161445.30809-2-longman@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- Documentation/admin-guide/hw-vuln/mds.rst | 7 +++++-- Documentation/admin-guide/hw-vuln/tsx_async_abort.rst | 5 ++++- Documentation/admin-guide/kernel-parameters.txt | 11 +++++++++++ arch/x86/kernel/cpu/bugs.c | 17 +++++++++++++++-- 4 files changed, 35 insertions(+), 5 deletions(-)
--- a/Documentation/admin-guide/hw-vuln/mds.rst +++ b/Documentation/admin-guide/hw-vuln/mds.rst @@ -265,8 +265,11 @@ time with the option "mds=". The valid a
============ =============================================================
-Not specifying this option is equivalent to "mds=full". - +Not specifying this option is equivalent to "mds=full". For processors +that are affected by both TAA (TSX Asynchronous Abort) and MDS, +specifying just "mds=off" without an accompanying "tsx_async_abort=off" +will have no effect as the same mitigation is used for both +vulnerabilities.
Mitigation selection guide -------------------------- --- a/Documentation/admin-guide/hw-vuln/tsx_async_abort.rst +++ b/Documentation/admin-guide/hw-vuln/tsx_async_abort.rst @@ -174,7 +174,10 @@ the option "tsx_async_abort=". The valid CPU is not vulnerable to cross-thread TAA attacks. ============ =============================================================
-Not specifying this option is equivalent to "tsx_async_abort=full". +Not specifying this option is equivalent to "tsx_async_abort=full". For +processors that are affected by both TAA and MDS, specifying just +"tsx_async_abort=off" without an accompanying "mds=off" will have no +effect as the same mitigation is used for both vulnerabilities.
The kernel command line also allows to control the TSX feature using the parameter "tsx=" on CPUs which support TSX control. MSR_IA32_TSX_CTRL is used --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -2449,6 +2449,12 @@ SMT on vulnerable CPUs off - Unconditionally disable MDS mitigation
+ On TAA-affected machines, mds=off can be prevented by + an active TAA mitigation as both vulnerabilities are + mitigated with the same mechanism so in order to disable + this mitigation, you need to specify tsx_async_abort=off + too. + Not specifying this option is equivalent to mds=full.
@@ -4896,6 +4902,11 @@ vulnerable to cross-thread TAA attacks. off - Unconditionally disable TAA mitigation
+ On MDS-affected machines, tsx_async_abort=off can be + prevented by an active MDS mitigation as both vulnerabilities + are mitigated with the same mechanism so in order to disable + this mitigation, you need to specify mds=off too. + Not specifying this option is equivalent to tsx_async_abort=full. On CPUs which are MDS affected and deploy MDS mitigation, TAA mitigation is not --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -304,8 +304,12 @@ static void __init taa_select_mitigation return; }
- /* TAA mitigation is turned off on the cmdline (tsx_async_abort=off) */ - if (taa_mitigation == TAA_MITIGATION_OFF) + /* + * TAA mitigation via VERW is turned off if both + * tsx_async_abort=off and mds=off are specified. + */ + if (taa_mitigation == TAA_MITIGATION_OFF && + mds_mitigation == MDS_MITIGATION_OFF) goto out;
if (boot_cpu_has(X86_FEATURE_MD_CLEAR)) @@ -339,6 +343,15 @@ static void __init taa_select_mitigation if (taa_nosmt || cpu_mitigations_auto_nosmt()) cpu_smt_disable(false);
+ /* + * Update MDS mitigation, if necessary, as the mds_user_clear is + * now enabled for TAA mitigation. + */ + if (mds_mitigation == MDS_MITIGATION_OFF && + boot_cpu_has_bug(X86_BUG_MDS)) { + mds_mitigation = MDS_MITIGATION_FULL; + mds_select_mitigation(); + } out: pr_info("%s\n", taa_strings[taa_mitigation]); }
From: Waiman Long longman@redhat.com
commit cd5a2aa89e847bdda7b62029d94e95488d73f6b2 upstream.
Since MDS and TAA mitigations are inter-related for processors that are affected by both vulnerabilities, the followiing confusing messages can be printed in the kernel log:
MDS: Vulnerable MDS: Mitigation: Clear CPU buffers
To avoid the first incorrect message, defer the printing of MDS mitigation after the TAA mitigation selection has been done. However, that has the side effect of printing TAA mitigation first before MDS mitigation.
[ bp: Check box is affected/mitigations are disabled first before printing and massage. ]
Suggested-by: Pawan Gupta pawan.kumar.gupta@linux.intel.com Signed-off-by: Waiman Long longman@redhat.com Signed-off-by: Borislav Petkov bp@suse.de Cc: Greg Kroah-Hartman gregkh@linuxfoundation.org Cc: "H. Peter Anvin" hpa@zytor.com Cc: Ingo Molnar mingo@redhat.com Cc: Josh Poimboeuf jpoimboe@redhat.com Cc: Mark Gross mgross@linux.intel.com Cc: Peter Zijlstra peterz@infradead.org Cc: Thomas Gleixner tglx@linutronix.de Cc: Tim Chen tim.c.chen@linux.intel.com Cc: Tony Luck tony.luck@intel.com Cc: Tyler Hicks tyhicks@canonical.com Cc: x86-ml x86@kernel.org Link: https://lkml.kernel.org/r/20191115161445.30809-3-longman@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/x86/kernel/cpu/bugs.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
--- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -39,6 +39,7 @@ static void __init spectre_v2_select_mit static void __init ssb_select_mitigation(void); static void __init l1tf_select_mitigation(void); static void __init mds_select_mitigation(void); +static void __init mds_print_mitigation(void); static void __init taa_select_mitigation(void);
/* The base value of the SPEC_CTRL MSR that always has to be preserved. */ @@ -108,6 +109,12 @@ void __init check_bugs(void) mds_select_mitigation(); taa_select_mitigation();
+ /* + * As MDS and TAA mitigations are inter-related, print MDS + * mitigation until after TAA mitigation selection is done. + */ + mds_print_mitigation(); + arch_smt_update();
#ifdef CONFIG_X86_32 @@ -245,6 +252,12 @@ static void __init mds_select_mitigation (mds_nosmt || cpu_mitigations_auto_nosmt())) cpu_smt_disable(false); } +} + +static void __init mds_print_mitigation(void) +{ + if (!boot_cpu_has_bug(X86_BUG_MDS) || cpu_mitigations_off()) + return;
pr_info("%s\n", mds_strings[mds_mitigation]); }
From: Navid Emamdoost navid.emamdoost@gmail.com
commit 03bf73c315edca28f47451913177e14cd040a216 upstream.
In nbd_add_socket when krealloc succeeds, if nsock's allocation fail the reallocted memory is leak. The correct behaviour should be assigning the reallocted memory to config->socks right after success.
Reviewed-by: Josef Bacik josef@toxicpanda.com Signed-off-by: Navid Emamdoost navid.emamdoost@gmail.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/block/nbd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
--- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -995,14 +995,15 @@ static int nbd_add_socket(struct nbd_dev sockfd_put(sock); return -ENOMEM; } + + config->socks = socks; + nsock = kzalloc(sizeof(struct nbd_sock), GFP_KERNEL); if (!nsock) { sockfd_put(sock); return -ENOMEM; }
- config->socks = socks; - nsock->fallback_index = -1; nsock->dead = false; mutex_init(&nsock->tx_lock);
From: Adi Suresh adisuresh@google.com
commit db96c2cb4870173ea9b08df130f1d1cc9b5dd53d upstream.
The previous commit had a bug where the last page in the memory range could not be synced. This change fixes the behavior so that all the required pages are synced.
Fixes: 9cfeeb576d49 ("gve: Fixes DMA synchronization") Signed-off-by: Adi Suresh adisuresh@google.com Reviewed-by: Catherine Sullivan csully@google.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/net/ethernet/google/gve/gve_tx.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
--- a/drivers/net/ethernet/google/gve/gve_tx.c +++ b/drivers/net/ethernet/google/gve/gve_tx.c @@ -393,12 +393,13 @@ static void gve_tx_fill_seg_desc(union g static void gve_dma_sync_for_device(struct device *dev, dma_addr_t *page_buses, u64 iov_offset, u64 iov_len) { + u64 last_page = (iov_offset + iov_len - 1) / PAGE_SIZE; + u64 first_page = iov_offset / PAGE_SIZE; dma_addr_t dma; - u64 addr; + u64 page;
- for (addr = iov_offset; addr < iov_offset + iov_len; - addr += PAGE_SIZE) { - dma = page_buses[addr / PAGE_SIZE]; + for (page = first_page; page <= last_page; page++) { + dma = page_buses[page]; dma_sync_single_for_device(dev, dma, PAGE_SIZE, DMA_TO_DEVICE); } }
From: Jan Beulich jbeulich@suse.com
commit 81ff2c37f9e5d77593928df0536d86443195fd64 upstream.
Once again RPL checks have been introduced which don't account for a 32-bit kernel living in ring 1 when running in a PV Xen domain. The case in FIXUP_FRAME has been preventing boot.
Adjust BUG_IF_WRONG_CR3 as well to guard against future uses of the macro on a code path reachable when running in PV mode under Xen; I have to admit that I stopped at a certain point trying to figure out whether there are present ones.
Fixes: 3c88c692c287 ("x86/stackframe/32: Provide consistent pt_regs") Signed-off-by: Jan Beulich jbeulich@suse.com Signed-off-by: Thomas Gleixner tglx@linutronix.de Cc: Stable Team stable@vger.kernel.org Link: https://lore.kernel.org/r/0fad341f-b7f5-f859-d55d-f0084ee7087e@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/x86/entry/entry_32.S | 4 ++-- arch/x86/include/asm/segment.h | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-)
--- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -172,7 +172,7 @@ ALTERNATIVE "jmp .Lend_@", "", X86_FEATURE_PTI .if \no_user_check == 0 /* coming from usermode? */ - testl $SEGMENT_RPL_MASK, PT_CS(%esp) + testl $USER_SEGMENT_RPL_MASK, PT_CS(%esp) jz .Lend_@ .endif /* On user-cr3? */ @@ -217,7 +217,7 @@ testl $X86_EFLAGS_VM, 4*4(%esp) jnz .Lfrom_usermode_no_fixup_@ #endif - testl $SEGMENT_RPL_MASK, 3*4(%esp) + testl $USER_SEGMENT_RPL_MASK, 3*4(%esp) jnz .Lfrom_usermode_no_fixup_@
orl $CS_FROM_KERNEL, 3*4(%esp) --- a/arch/x86/include/asm/segment.h +++ b/arch/x86/include/asm/segment.h @@ -31,6 +31,18 @@ */ #define SEGMENT_RPL_MASK 0x3
+/* + * When running on Xen PV, the actual privilege level of the kernel is 1, + * not 0. Testing the Requested Privilege Level in a segment selector to + * determine whether the context is user mode or kernel mode with + * SEGMENT_RPL_MASK is wrong because the PV kernel's privilege level + * matches the 0x3 mask. + * + * Testing with USER_SEGMENT_RPL_MASK is valid for both native and Xen PV + * kernels because privilege level 2 is never used. + */ +#define USER_SEGMENT_RPL_MASK 0x2 + /* User mode is privilege level 3: */ #define USER_RPL 0x3
From: Jan Beulich jbeulich@suse.com
commit 29b810f5a5ec127d3143770098e05981baa3eb77 upstream.
Now that SS:ESP always get saved by SAVE_ALL, this also needs to be accounted for in xen_iret_crit_fixup(). Otherwise the old_ax value gets interpreted as EFLAGS, and hence VM86 mode appears to be active all the time, leading to random "vm86_32: no user_vm86: BAD" log messages alongside processes randomly crashing.
Since following the previous model (sitting after SAVE_ALL) would further complicate the code _and_ retain the dependency of xen_iret_crit_fixup() on frame manipulations done by entry_32.S, switch things around and do the adjustment ahead of SAVE_ALL.
Fixes: 3c88c692c287 ("x86/stackframe/32: Provide consistent pt_regs") Signed-off-by: Jan Beulich jbeulich@suse.com Signed-off-by: Thomas Gleixner tglx@linutronix.de Reviewed-by: Juergen Gross jgross@suse.com Cc: Stable Team stable@vger.kernel.org Link: https://lkml.kernel.org/r/32d8713d-25a7-84ab-b74b-aa3e88abce6b@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/x86/entry/entry_32.S | 22 +++++--------- arch/x86/xen/xen-asm_32.S | 70 +++++++++++++++++----------------------------- 2 files changed, 35 insertions(+), 57 deletions(-)
--- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -1341,11 +1341,6 @@ END(spurious_interrupt_bug)
#ifdef CONFIG_XEN_PV ENTRY(xen_hypervisor_callback) - pushl $-1 /* orig_ax = -1 => not a system call */ - SAVE_ALL - ENCODE_FRAME_POINTER - TRACE_IRQS_OFF - /* * Check to see if we got the event in the critical * region in xen_iret_direct, after we've reenabled @@ -1353,16 +1348,17 @@ ENTRY(xen_hypervisor_callback) * iret instruction's behaviour where it delivers a * pending interrupt when enabling interrupts: */ - movl PT_EIP(%esp), %eax - cmpl $xen_iret_start_crit, %eax + cmpl $xen_iret_start_crit, (%esp) jb 1f - cmpl $xen_iret_end_crit, %eax + cmpl $xen_iret_end_crit, (%esp) jae 1f - - jmp xen_iret_crit_fixup - -ENTRY(xen_do_upcall) -1: mov %esp, %eax + call xen_iret_crit_fixup +1: + pushl $-1 /* orig_ax = -1 => not a system call */ + SAVE_ALL + ENCODE_FRAME_POINTER + TRACE_IRQS_OFF + mov %esp, %eax call xen_evtchn_do_upcall #ifndef CONFIG_PREEMPT call xen_maybe_preempt_hcall --- a/arch/x86/xen/xen-asm_32.S +++ b/arch/x86/xen/xen-asm_32.S @@ -126,10 +126,9 @@ hyper_iret: .globl xen_iret_start_crit, xen_iret_end_crit
/* - * This is called by xen_hypervisor_callback in entry.S when it sees + * This is called by xen_hypervisor_callback in entry_32.S when it sees * that the EIP at the time of interrupt was between - * xen_iret_start_crit and xen_iret_end_crit. We're passed the EIP in - * %eax so we can do a more refined determination of what to do. + * xen_iret_start_crit and xen_iret_end_crit. * * The stack format at this point is: * ---------------- @@ -138,34 +137,23 @@ hyper_iret: * eflags } outer exception info * cs } * eip } - * ---------------- <- edi (copy dest) - * eax : outer eax if it hasn't been restored * ---------------- - * eflags } nested exception info - * cs } (no ss/esp because we're nested - * eip } from the same ring) - * orig_eax }<- esi (copy src) - * - - - - - - - - - * fs } - * es } - * ds } SAVE_ALL state - * eax } - * : : - * ebx }<- esp + * eax : outer eax if it hasn't been restored * ---------------- + * eflags } + * cs } nested exception info + * eip } + * return address : (into xen_hypervisor_callback) * - * In order to deliver the nested exception properly, we need to shift - * everything from the return addr up to the error code so it sits - * just under the outer exception info. This means that when we - * handle the exception, we do it in the context of the outer - * exception rather than starting a new one. + * In order to deliver the nested exception properly, we need to discard the + * nested exception frame such that when we handle the exception, we do it + * in the context of the outer exception rather than starting a new one. * - * The only caveat is that if the outer eax hasn't been restored yet - * (ie, it's still on stack), we need to insert its value into the - * SAVE_ALL state before going on, since it's usermode state which we - * eventually need to restore. + * The only caveat is that if the outer eax hasn't been restored yet (i.e. + * it's still on stack), we need to restore its value here. */ ENTRY(xen_iret_crit_fixup) + pushl %ecx /* * Paranoia: Make sure we're really coming from kernel space. * One could imagine a case where userspace jumps into the @@ -176,32 +164,26 @@ ENTRY(xen_iret_crit_fixup) * jump instruction itself, not the destination, but some * virtual environments get this wrong. */ - movl PT_CS(%esp), %ecx + movl 3*4(%esp), %ecx /* nested CS */ andl $SEGMENT_RPL_MASK, %ecx cmpl $USER_RPL, %ecx + popl %ecx je 2f
- lea PT_ORIG_EAX(%esp), %esi - lea PT_EFLAGS(%esp), %edi - /* * If eip is before iret_restore_end then stack * hasn't been restored yet. */ - cmp $iret_restore_end, %eax + cmpl $iret_restore_end, 1*4(%esp) jae 1f
- movl 0+4(%edi), %eax /* copy EAX (just above top of frame) */ - movl %eax, PT_EAX(%esp) - - lea ESP_OFFSET(%edi), %edi /* move dest up over saved regs */ - - /* set up the copy */ -1: std - mov $PT_EIP / 4, %ecx /* saved regs up to orig_eax */ - rep movsl - cld - - lea 4(%edi), %esp /* point esp to new frame */ -2: jmp xen_do_upcall - + movl 4*4(%esp), %eax /* load outer EAX */ + ret $4*4 /* discard nested EIP, CS, and EFLAGS as + * well as the just restored EAX */ + +1: + ret $3*4 /* discard nested EIP, CS, and EFLAGS */ + +2: + ret +END(xen_iret_crit_fixup)
From: Jan Beulich jbeulich@suse.com
commit 922eea2ce5c799228d9ff1be9890e6873ce8fff6 upstream.
This can be had with two instead of six insns, by just checking the high CS.RPL bit.
Also adjust the comment - there would be no #GP in the mentioned cases, as there's no segment limit violation or alike. Instead there'd be #PF, but that one reports the target EIP of said branch, not the address of the branch insn itself.
Signed-off-by: Jan Beulich jbeulich@suse.com Signed-off-by: Thomas Gleixner tglx@linutronix.de Reviewed-by: Juergen Gross jgross@suse.com Link: https://lkml.kernel.org/r/a5986837-01eb-7bf8-bf42-4d3084d6a1f5@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/x86/xen/xen-asm_32.S | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-)
--- a/arch/x86/xen/xen-asm_32.S +++ b/arch/x86/xen/xen-asm_32.S @@ -153,22 +153,15 @@ hyper_iret: * it's still on stack), we need to restore its value here. */ ENTRY(xen_iret_crit_fixup) - pushl %ecx /* * Paranoia: Make sure we're really coming from kernel space. * One could imagine a case where userspace jumps into the * critical range address, but just before the CPU delivers a - * GP, it decides to deliver an interrupt instead. Unlikely? - * Definitely. Easy to avoid? Yes. The Intel documents - * explicitly say that the reported EIP for a bad jump is the - * jump instruction itself, not the destination, but some - * virtual environments get this wrong. + * PF, it decides to deliver an interrupt instead. Unlikely? + * Definitely. Easy to avoid? Yes. */ - movl 3*4(%esp), %ecx /* nested CS */ - andl $SEGMENT_RPL_MASK, %ecx - cmpl $USER_RPL, %ecx - popl %ecx - je 2f + testb $2, 2*4(%esp) /* nested CS */ + jnz 2f
/* * If eip is before iret_restore_end then stack
From: Andy Lutomirski luto@kernel.org
commit 3580d0b29cab08483f84a16ce6a1151a1013695f upstream.
The double fault TSS was missing GS setup, which is needed for stack canaries to work.
Signed-off-by: Andy Lutomirski luto@kernel.org Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Cc: stable@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/x86/kernel/doublefault.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/arch/x86/kernel/doublefault.c +++ b/arch/x86/kernel/doublefault.c @@ -65,6 +65,9 @@ struct x86_hw_tss doublefault_tss __cach .ss = __KERNEL_DS, .ds = __USER_DS, .fs = __KERNEL_PERCPU, +#ifndef CONFIG_X86_32_LAZY_GS + .gs = __KERNEL_STACK_CANARY, +#endif
.__cr3 = __pa_nodebug(swapper_pg_dir), };
From: Thomas Gleixner tglx@linutronix.de
commit f490e07c53d66045d9d739e134145ec9b38653d3 upstream.
Commit 945fd17ab6ba ("x86/cpu_entry_area: Sync cpu_entry_area to initial_page_table") introduced the sync for the initial page table for 32bit.
sync_initial_page_table() uses clone_pgd_range() which does the update for the kernel page table. If PTI is enabled it also updates the user space page table counterpart, which is assumed to be in the next page after the target PGD.
At this point in time 32-bit did not have PTI support, so the user space page table update was not taking place.
The support for PTI on 32-bit which was introduced later on, did not take that into account and missed to add the user space counter part for the initial page table.
As a consequence sync_initial_page_table() overwrites any data which is located in the page behing initial_page_table causing random failures, e.g. by corrupting doublefault_tss and wreckaging the doublefault handler on 32bit.
Fix it by adding a "user" page table right after initial_page_table.
Fixes: 7757d607c6b3 ("x86/pti: Allow CONFIG_PAGE_TABLE_ISOLATION for x86_32") Signed-off-by: Thomas Gleixner tglx@linutronix.de Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Reviewed-by: Joerg Roedel jroedel@suse.de Cc: stable@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/x86/kernel/head_32.S | 10 ++++++++++ 1 file changed, 10 insertions(+)
--- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -571,6 +571,16 @@ ENTRY(initial_page_table) # error "Kernel PMDs should be 1, 2 or 3" # endif .align PAGE_SIZE /* needs to be page-sized too */ + +#ifdef CONFIG_PAGE_TABLE_ISOLATION + /* + * PTI needs another page so sync_initial_pagetable() works correctly + * and does not scribble over the data which is placed behind the + * actual initial_page_table. See clone_pgd_range(). + */ + .fill 1024, 4, 0 +#endif + #endif
.data
From: Thomas Gleixner tglx@linutronix.de
commit 880a98c339961eaa074393e3a2117cbe9125b8bb upstream.
The entry stack in the cpu entry area is protected against overflow by the readonly GDT on 64-bit, but on 32-bit the GDT needs to be writeable and therefore does not trigger a fault on stack overflow.
Add a guard page.
Fixes: c482feefe1ae ("x86/entry/64: Make cpu_entry_area.tss read-only") Signed-off-by: Thomas Gleixner tglx@linutronix.de Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Cc: stable@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/x86/include/asm/cpu_entry_area.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
--- a/arch/x86/include/asm/cpu_entry_area.h +++ b/arch/x86/include/asm/cpu_entry_area.h @@ -78,8 +78,12 @@ struct cpu_entry_area {
/* * The GDT is just below entry_stack and thus serves (on x86_64) as - * a a read-only guard page. + * a read-only guard page. On 32-bit the GDT must be writeable, so + * it needs an extra guard page. */ +#ifdef CONFIG_X86_32 + char guard_entry_stack[PAGE_SIZE]; +#endif struct entry_stack_page entry_stack_page;
/*
From: Peter Zijlstra peterz@infradead.org
commit 40ad2199580e248dce2a2ebb722854180c334b9e upstream.
As reported by Lai, the commit 3c88c692c287 ("x86/stackframe/32: Provide consistent pt_regs") wrecked the IRET EXTABLE entry by making .Lirq_return not point at IRET.
Fix this by placing IRET_FRAME in RESTORE_REGS, to mirror how FIXUP_FRAME is part of SAVE_ALL.
Fixes: 3c88c692c287 ("x86/stackframe/32: Provide consistent pt_regs") Reported-by: Lai Jiangshan laijs@linux.alibaba.com Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Acked-by: Andy Lutomirski luto@kernel.org Cc: stable@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/x86/entry/entry_32.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -357,6 +357,7 @@ 2: popl %es 3: popl %fs POP_GS \pop + IRET_FRAME .pushsection .fixup, "ax" 4: movl $0, (%esp) jmp 1b @@ -1075,7 +1076,6 @@ restore_all: /* Restore user state */ RESTORE_REGS pop=4 # skip orig_eax/error_code .Lirq_return: - IRET_FRAME /* * ARCH_HAS_MEMBARRIER_SYNC_CORE rely on IRET core serialization * when returning from IPI handler and when returning from
From: Andy Lutomirski luto@kernel.org
commit 4c4fd55d3d59a41ddfa6ecba7e76928921759f43 upstream.
When re-building the IRET frame we use %eax as an destination %esp, make sure to then also match the segment for when there is a nonzero SS base (ESPFIX).
[peterz: Changelog and minor edits] Fixes: 3c88c692c287 ("x86/stackframe/32: Provide consistent pt_regs") Signed-off-by: Andy Lutomirski luto@kernel.org Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Cc: stable@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/x86/entry/entry_32.S | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-)
--- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -210,6 +210,8 @@ /* * The high bits of the CS dword (__csh) are used for CS_FROM_*. * Clear them in case hardware didn't do this for us. + * + * Be careful: we may have nonzero SS base due to ESPFIX. */ andl $0x0000ffff, 3*4(%esp)
@@ -263,6 +265,13 @@ .endm
.macro IRET_FRAME + /* + * We're called with %ds, %es, %fs, and %gs from the interrupted + * frame, so we shouldn't use them. Also, we may be in ESPFIX + * mode and therefore have a nonzero SS base and an offset ESP, + * so any attempt to access the stack needs to use SS. (except for + * accesses through %esp, which automatically use SS.) + */ testl $CS_FROM_KERNEL, 1*4(%esp) jz .Lfinished_frame_@
@@ -276,20 +285,20 @@ movl 5*4(%esp), %eax # (modified) regs->sp
movl 4*4(%esp), %ecx # flags - movl %ecx, -4(%eax) + movl %ecx, %ss:-1*4(%eax)
movl 3*4(%esp), %ecx # cs andl $0x0000ffff, %ecx - movl %ecx, -8(%eax) + movl %ecx, %ss:-2*4(%eax)
movl 2*4(%esp), %ecx # ip - movl %ecx, -12(%eax) + movl %ecx, %ss:-3*4(%eax)
movl 1*4(%esp), %ecx # eax - movl %ecx, -16(%eax) + movl %ecx, %ss:-4*4(%eax)
popl %ecx - lea -16(%eax), %esp + lea -4*4(%eax), %esp popl %eax .Lfinished_frame_@: .endm
From: Andy Lutomirski luto@kernel.org
commit 82cb8a0b1d8d07817b5d59f7fa1438e1fceafab2 upstream.
This will allow us to get percpu access working before FIXUP_FRAME, which will allow us to unwind ESPFIX earlier.
Signed-off-by: Andy Lutomirski luto@kernel.org Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Cc: stable@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/x86/entry/entry_32.S | 66 ++++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 31 deletions(-)
--- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -213,54 +213,58 @@ * * Be careful: we may have nonzero SS base due to ESPFIX. */ - andl $0x0000ffff, 3*4(%esp) + andl $0x0000ffff, 4*4(%esp)
#ifdef CONFIG_VM86 - testl $X86_EFLAGS_VM, 4*4(%esp) + testl $X86_EFLAGS_VM, 5*4(%esp) jnz .Lfrom_usermode_no_fixup_@ #endif - testl $USER_SEGMENT_RPL_MASK, 3*4(%esp) + testl $USER_SEGMENT_RPL_MASK, 4*4(%esp) jnz .Lfrom_usermode_no_fixup_@
- orl $CS_FROM_KERNEL, 3*4(%esp) + orl $CS_FROM_KERNEL, 4*4(%esp)
/* * When we're here from kernel mode; the (exception) stack looks like: * - * 5*4(%esp) - <previous context> - * 4*4(%esp) - flags - * 3*4(%esp) - cs - * 2*4(%esp) - ip - * 1*4(%esp) - orig_eax - * 0*4(%esp) - gs / function + * 6*4(%esp) - <previous context> + * 5*4(%esp) - flags + * 4*4(%esp) - cs + * 3*4(%esp) - ip + * 2*4(%esp) - orig_eax + * 1*4(%esp) - gs / function + * 0*4(%esp) - fs * * Lets build a 5 entry IRET frame after that, such that struct pt_regs * is complete and in particular regs->sp is correct. This gives us - * the original 5 enties as gap: + * the original 6 enties as gap: * - * 12*4(%esp) - <previous context> - * 11*4(%esp) - gap / flags - * 10*4(%esp) - gap / cs - * 9*4(%esp) - gap / ip - * 8*4(%esp) - gap / orig_eax - * 7*4(%esp) - gap / gs / function - * 6*4(%esp) - ss - * 5*4(%esp) - sp - * 4*4(%esp) - flags - * 3*4(%esp) - cs - * 2*4(%esp) - ip - * 1*4(%esp) - orig_eax - * 0*4(%esp) - gs / function + * 14*4(%esp) - <previous context> + * 13*4(%esp) - gap / flags + * 12*4(%esp) - gap / cs + * 11*4(%esp) - gap / ip + * 10*4(%esp) - gap / orig_eax + * 9*4(%esp) - gap / gs / function + * 8*4(%esp) - gap / fs + * 7*4(%esp) - ss + * 6*4(%esp) - sp + * 5*4(%esp) - flags + * 4*4(%esp) - cs + * 3*4(%esp) - ip + * 2*4(%esp) - orig_eax + * 1*4(%esp) - gs / function + * 0*4(%esp) - fs */
pushl %ss # ss pushl %esp # sp (points at ss) - addl $6*4, (%esp) # point sp back at the previous context - pushl 6*4(%esp) # flags - pushl 6*4(%esp) # cs - pushl 6*4(%esp) # ip - pushl 6*4(%esp) # orig_eax - pushl 6*4(%esp) # gs / function + addl $7*4, (%esp) # point sp back at the previous context + pushl 7*4(%esp) # flags + pushl 7*4(%esp) # cs + pushl 7*4(%esp) # ip + pushl 7*4(%esp) # orig_eax + pushl 7*4(%esp) # gs / function + pushl 7*4(%esp) # fs .Lfrom_usermode_no_fixup_@: .endm
@@ -308,8 +312,8 @@ .if \skip_gs == 0 PUSH_GS .endif - FIXUP_FRAME pushl %fs + FIXUP_FRAME pushl %es pushl %ds pushl \pt_regs_ax
From: Andy Lutomirski luto@kernel.org
commit a1a338e5b6fe9e0a39c57c232dc96c198bb53e47 upstream.
Right now, we do some fancy parts of the exception entry path while SS might have a nonzero base: we fill in regs->ss and regs->sp, and we consider switching to the kernel stack. This results in regs->ss and regs->sp referring to a non-flat stack and it may result in overflowing the entry stack. The former issue means that we can try to call iret_exc on a non-flat stack, which doesn't work.
Tested with selftests/x86/sigreturn_32.
Fixes: 45d7b255747c ("x86/entry/32: Enter the kernel via trampoline stack") Signed-off-by: Andy Lutomirski luto@kernel.org Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Cc: stable@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/x86/entry/entry_32.S | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-)
--- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -210,8 +210,6 @@ /* * The high bits of the CS dword (__csh) are used for CS_FROM_*. * Clear them in case hardware didn't do this for us. - * - * Be careful: we may have nonzero SS base due to ESPFIX. */ andl $0x0000ffff, 4*4(%esp)
@@ -307,12 +305,21 @@ .Lfinished_frame_@: .endm
-.macro SAVE_ALL pt_regs_ax=%eax switch_stacks=0 skip_gs=0 +.macro SAVE_ALL pt_regs_ax=%eax switch_stacks=0 skip_gs=0 unwind_espfix=0 cld .if \skip_gs == 0 PUSH_GS .endif pushl %fs + + pushl %eax + movl $(__KERNEL_PERCPU), %eax + movl %eax, %fs +.if \unwind_espfix > 0 + UNWIND_ESPFIX_STACK +.endif + popl %eax + FIXUP_FRAME pushl %es pushl %ds @@ -326,8 +333,6 @@ movl $(__USER_DS), %edx movl %edx, %ds movl %edx, %es - movl $(__KERNEL_PERCPU), %edx - movl %edx, %fs .if \skip_gs == 0 SET_KERNEL_GS %edx .endif @@ -1153,18 +1158,17 @@ ENDPROC(entry_INT80_32) lss (%esp), %esp /* switch to the normal stack segment */ #endif .endm + .macro UNWIND_ESPFIX_STACK + /* It's safe to clobber %eax, all other regs need to be preserved */ #ifdef CONFIG_X86_ESPFIX32 movl %ss, %eax /* see if on espfix stack */ cmpw $__ESPFIX_SS, %ax - jne 27f - movl $__KERNEL_DS, %eax - movl %eax, %ds - movl %eax, %es + jne .Lno_fixup_@ /* switch to normal stack */ FIXUP_ESPFIX_STACK -27: +.Lno_fixup_@: #endif .endm
@@ -1458,10 +1462,9 @@ END(page_fault)
common_exception_read_cr2: /* the function address is in %gs's slot on the stack */ - SAVE_ALL switch_stacks=1 skip_gs=1 + SAVE_ALL switch_stacks=1 skip_gs=1 unwind_espfix=1
ENCODE_FRAME_POINTER - UNWIND_ESPFIX_STACK
/* fixup %gs */ GS_TO_REG %ecx @@ -1483,9 +1486,8 @@ END(common_exception_read_cr2)
common_exception: /* the function address is in %gs's slot on the stack */ - SAVE_ALL switch_stacks=1 skip_gs=1 + SAVE_ALL switch_stacks=1 skip_gs=1 unwind_espfix=1 ENCODE_FRAME_POINTER - UNWIND_ESPFIX_STACK
/* fixup %gs */ GS_TO_REG %ecx
From: Peter Zijlstra peterz@infradead.org
commit 895429076512e9d1cf5428181076299c90713159 upstream.
When the NMI lands on an ESPFIX_SS, we are on the entry stack and must swizzle, otherwise we'll run do_nmi() on the entry stack, which is BAD.
Also, similar to the normal exception path, we need to correct the ESPFIX magic before leaving the entry stack, otherwise pt_regs will present a non-flat stack pointer.
Tested by running sigreturn_32 concurrent with perf-record.
Fixes: e5862d0515ad ("x86/entry/32: Leave the kernel via trampoline stack") Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Acked-by: Andy Lutomirski luto@kernel.org Cc: stable@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/x86/entry/entry_32.S | 53 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 12 deletions(-)
--- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -205,6 +205,7 @@ #define CS_FROM_ENTRY_STACK (1 << 31) #define CS_FROM_USER_CR3 (1 << 30) #define CS_FROM_KERNEL (1 << 29) +#define CS_FROM_ESPFIX (1 << 28)
.macro FIXUP_FRAME /* @@ -342,8 +343,8 @@ .endif .endm
-.macro SAVE_ALL_NMI cr3_reg:req - SAVE_ALL +.macro SAVE_ALL_NMI cr3_reg:req unwind_espfix=0 + SAVE_ALL unwind_espfix=\unwind_espfix
BUG_IF_WRONG_CR3
@@ -1526,6 +1527,10 @@ ENTRY(nmi) ASM_CLAC
#ifdef CONFIG_X86_ESPFIX32 + /* + * ESPFIX_SS is only ever set on the return to user path + * after we've switched to the entry stack. + */ pushl %eax movl %ss, %eax cmpw $__ESPFIX_SS, %ax @@ -1561,6 +1566,11 @@ ENTRY(nmi) movl %ebx, %esp
.Lnmi_return: +#ifdef CONFIG_X86_ESPFIX32 + testl $CS_FROM_ESPFIX, PT_CS(%esp) + jnz .Lnmi_from_espfix +#endif + CHECK_AND_APPLY_ESPFIX RESTORE_ALL_NMI cr3_reg=%edi pop=4 jmp .Lirq_return @@ -1568,23 +1578,42 @@ ENTRY(nmi) #ifdef CONFIG_X86_ESPFIX32 .Lnmi_espfix_stack: /* - * create the pointer to lss back + * Create the pointer to LSS back */ pushl %ss pushl %esp addl $4, (%esp) - /* copy the iret frame of 12 bytes */ - .rept 3 - pushl 16(%esp) - .endr - pushl %eax - SAVE_ALL_NMI cr3_reg=%edi + + /* Copy the (short) IRET frame */ + pushl 4*4(%esp) # flags + pushl 4*4(%esp) # cs + pushl 4*4(%esp) # ip + + pushl %eax # orig_ax + + SAVE_ALL_NMI cr3_reg=%edi unwind_espfix=1 ENCODE_FRAME_POINTER - FIXUP_ESPFIX_STACK # %eax == %esp + + /* clear CS_FROM_KERNEL, set CS_FROM_ESPFIX */ + xorl $(CS_FROM_ESPFIX | CS_FROM_KERNEL), PT_CS(%esp) + xorl %edx, %edx # zero error code - call do_nmi + movl %esp, %eax # pt_regs pointer + jmp .Lnmi_from_sysenter_stack + +.Lnmi_from_espfix: RESTORE_ALL_NMI cr3_reg=%edi - lss 12+4(%esp), %esp # back to espfix stack + /* + * Because we cleared CS_FROM_KERNEL, IRET_FRAME 'forgot' to + * fix up the gap and long frame: + * + * 3 - original frame (exception) + * 2 - ESPFIX block (above) + * 6 - gap (FIXUP_FRAME) + * 5 - long frame (FIXUP_FRAME) + * 1 - orig_ax + */ + lss (1+5+6)*4(%esp), %esp # back to espfix stack jmp .Lirq_return #endif END(nmi)
From: Andy Lutomirski luto@kernel.org
commit 8caa016bfc129f2c925d52da43022171d1d1de91 upstream.
For reasons that I haven't quite fully diagnosed, running mov_ss_trap_32 on a 32-bit kernel results in an infinite loop in userspace. This appears to be because the hacky SYSENTER test doesn't segfault as desired; instead it corrupts the program state such that it infinite loops.
Fix it by explicitly clearing EBP before doing SYSENTER. This will give a more reliable segfault.
Fixes: 59c2a7226fc5 ("x86/selftests: Add mov_to_ss test") Signed-off-by: Andy Lutomirski luto@kernel.org Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Cc: stable@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- tools/testing/selftests/x86/mov_ss_trap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/tools/testing/selftests/x86/mov_ss_trap.c +++ b/tools/testing/selftests/x86/mov_ss_trap.c @@ -257,7 +257,8 @@ int main() err(1, "sigaltstack"); sethandler(SIGSEGV, handle_and_longjmp, SA_RESETHAND | SA_ONSTACK); nr = SYS_getpid; - asm volatile ("mov %[ss], %%ss; SYSENTER" : "+a" (nr) + /* Clear EBP first to make sure we segfault cleanly. */ + asm volatile ("xorl %%ebp, %%ebp; mov %[ss], %%ss; SYSENTER" : "+a" (nr) : [ss] "m" (ss) : "flags", "rcx" #ifdef __x86_64__ , "r11"
From: Andy Lutomirski luto@kernel.org
commit 4d2fa82d98d2d296043a04eb517d7dbade5b13b8 upstream.
If the kernel accidentally uses DS or ES while the user values are loaded, it will work fine for sane userspace. In the interest of simulating maximally insane userspace, make sigreturn_32 zero out DS and ES for the nasty parts so that inadvertent use of these segments will crash.
Signed-off-by: Andy Lutomirski luto@kernel.org Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Cc: stable@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- tools/testing/selftests/x86/sigreturn.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
--- a/tools/testing/selftests/x86/sigreturn.c +++ b/tools/testing/selftests/x86/sigreturn.c @@ -451,6 +451,19 @@ static void sigusr1(int sig, siginfo_t * ctx->uc_mcontext.gregs[REG_SP] = (unsigned long)0x8badf00d5aadc0deULL; ctx->uc_mcontext.gregs[REG_CX] = 0;
+#ifdef __i386__ + /* + * Make sure the kernel doesn't inadvertently use DS or ES-relative + * accesses in a region where user DS or ES is loaded. + * + * Skip this for 64-bit builds because long mode doesn't care about + * DS and ES and skipping it increases test coverage a little bit, + * since 64-bit kernels can still run the 32-bit build. + */ + ctx->uc_mcontext.gregs[REG_DS] = 0; + ctx->uc_mcontext.gregs[REG_ES] = 0; +#endif + memcpy(&requested_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t)); requested_regs[REG_CX] = *ssptr(ctx); /* The asm code does this. */
From: Ingo Molnar mingo@kernel.org
commit 05b042a1944322844eaae7ea596d5f154166d68a upstream.
When two recent commits that increased the size of the 'struct cpu_entry_area' were merged in -tip, the 32-bit defconfig build started failing on the following build time assert:
./include/linux/compiler.h:391:38: error: call to ‘__compiletime_assert_189’ declared with attribute error: BUILD_BUG_ON failed: CPU_ENTRY_AREA_PAGES * PAGE_SIZE < CPU_ENTRY_AREA_MAP_SIZE arch/x86/mm/cpu_entry_area.c:189:2: note: in expansion of macro ‘BUILD_BUG_ON’ In function ‘setup_cpu_entry_area_ptes’,
Which corresponds to the following build time assert:
BUILD_BUG_ON(CPU_ENTRY_AREA_PAGES * PAGE_SIZE < CPU_ENTRY_AREA_MAP_SIZE);
The purpose of this assert is to sanity check the fixed-value definition of CPU_ENTRY_AREA_PAGES arch/x86/include/asm/pgtable_32_types.h:
#define CPU_ENTRY_AREA_PAGES (NR_CPUS * 41)
The '41' is supposed to match sizeof(struct cpu_entry_area)/PAGE_SIZE, which value we didn't want to define in such a low level header, because it would cause dependency hell.
Every time the size of cpu_entry_area is changed, we have to adjust CPU_ENTRY_AREA_PAGES accordingly - and this assert is checking that constraint.
But the assert is both imprecise and buggy, primarily because it doesn't include the single readonly IDT page that is mapped at CPU_ENTRY_AREA_BASE (which begins at a PMD boundary).
This bug was hidden by the fact that by accident CPU_ENTRY_AREA_PAGES is defined too large upstream (v5.4-rc8):
#define CPU_ENTRY_AREA_PAGES (NR_CPUS * 40)
While 'struct cpu_entry_area' is 155648 bytes, or 38 pages. So we had two extra pages, which hid the bug.
The following commit (not yet upstream) increased the size to 40 pages:
x86/iopl: ("Restrict iopl() permission scope")
... but increased CPU_ENTRY_AREA_PAGES only 41 - i.e. shortening the gap to just 1 extra page.
Then another not-yet-upstream commit changed the size again:
880a98c33996: ("x86/cpu_entry_area: Add guard page for entry stack on 32bit")
Which increased the cpu_entry_area size from 38 to 39 pages, but didn't change CPU_ENTRY_AREA_PAGES (kept it at 40). This worked fine, because we still had a page left from the accidental 'reserve'.
But when these two commits were merged into the same tree, the combined size of cpu_entry_area grew from 38 to 40 pages, while CPU_ENTRY_AREA_PAGES finally caught up to 40 as well.
Which is fine in terms of functionality, but the assert broke:
BUILD_BUG_ON(CPU_ENTRY_AREA_PAGES * PAGE_SIZE < CPU_ENTRY_AREA_MAP_SIZE);
because CPU_ENTRY_AREA_MAP_SIZE is the total size of the area, which is 1 page larger due to the IDT page.
To fix all this, change the assert to two precise asserts:
BUILD_BUG_ON((CPU_ENTRY_AREA_PAGES+1)*PAGE_SIZE != CPU_ENTRY_AREA_MAP_SIZE); BUILD_BUG_ON(CPU_ENTRY_AREA_TOTAL_SIZE != CPU_ENTRY_AREA_MAP_SIZE);
This takes the IDT page into account, and also connects the size-based define of CPU_ENTRY_AREA_TOTAL_SIZE with the address-subtraction based define of CPU_ENTRY_AREA_MAP_SIZE.
Also clean up some of the names which made it rather confusing:
- 'CPU_ENTRY_AREA_TOT_SIZE' wasn't actually the 'total' size of the cpu-entry-area, but the per-cpu array size, so rename this to CPU_ENTRY_AREA_ARRAY_SIZE.
- Introduce CPU_ENTRY_AREA_TOTAL_SIZE that _is_ the total mapping size, with the IDT included.
- Add comments where '+1' denotes the IDT mapping - it wasn't obvious and took me about 3 hours to decode...
Finally, because this particular commit is actually applied after this patch:
880a98c33996: ("x86/cpu_entry_area: Add guard page for entry stack on 32bit")
Fix the CPU_ENTRY_AREA_PAGES value from 40 pages to the correct 39 pages.
All future commits that change cpu_entry_area will have to adjust this value precisely.
As a side note, we should probably attempt to remove CPU_ENTRY_AREA_PAGES and derive its value directly from the structure, without causing header hell - but that is an adventure for another day! :-)
Fixes: 880a98c33996: ("x86/cpu_entry_area: Add guard page for entry stack on 32bit") Cc: Thomas Gleixner tglx@linutronix.de Cc: Borislav Petkov bp@alien8.de Cc: Peter Zijlstra (Intel) peterz@infradead.org Cc: Linus Torvalds torvalds@linux-foundation.org Cc: Andy Lutomirski luto@kernel.org Cc: stable@kernel.org Signed-off-by: Ingo Molnar mingo@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/x86/include/asm/cpu_entry_area.h | 12 +++++++----- arch/x86/include/asm/pgtable_32_types.h | 8 ++++---- arch/x86/mm/cpu_entry_area.c | 4 +++- 3 files changed, 14 insertions(+), 10 deletions(-)
--- a/arch/x86/include/asm/cpu_entry_area.h +++ b/arch/x86/include/asm/cpu_entry_area.h @@ -98,7 +98,6 @@ struct cpu_entry_area { */ struct cea_exception_stacks estacks; #endif -#ifdef CONFIG_CPU_SUP_INTEL /* * Per CPU debug store for Intel performance monitoring. Wastes a * full page at the moment. @@ -109,11 +108,13 @@ struct cpu_entry_area { * Reserve enough fixmap PTEs. */ struct debug_store_buffers cpu_debug_buffers; -#endif };
-#define CPU_ENTRY_AREA_SIZE (sizeof(struct cpu_entry_area)) -#define CPU_ENTRY_AREA_TOT_SIZE (CPU_ENTRY_AREA_SIZE * NR_CPUS) +#define CPU_ENTRY_AREA_SIZE (sizeof(struct cpu_entry_area)) +#define CPU_ENTRY_AREA_ARRAY_SIZE (CPU_ENTRY_AREA_SIZE * NR_CPUS) + +/* Total size includes the readonly IDT mapping page as well: */ +#define CPU_ENTRY_AREA_TOTAL_SIZE (CPU_ENTRY_AREA_ARRAY_SIZE + PAGE_SIZE)
DECLARE_PER_CPU(struct cpu_entry_area *, cpu_entry_area); DECLARE_PER_CPU(struct cea_exception_stacks *, cea_exception_stacks); @@ -121,13 +122,14 @@ DECLARE_PER_CPU(struct cea_exception_sta extern void setup_cpu_entry_areas(void); extern void cea_set_pte(void *cea_vaddr, phys_addr_t pa, pgprot_t flags);
+/* Single page reserved for the readonly IDT mapping: */ #define CPU_ENTRY_AREA_RO_IDT CPU_ENTRY_AREA_BASE #define CPU_ENTRY_AREA_PER_CPU (CPU_ENTRY_AREA_RO_IDT + PAGE_SIZE)
#define CPU_ENTRY_AREA_RO_IDT_VADDR ((void *)CPU_ENTRY_AREA_RO_IDT)
#define CPU_ENTRY_AREA_MAP_SIZE \ - (CPU_ENTRY_AREA_PER_CPU + CPU_ENTRY_AREA_TOT_SIZE - CPU_ENTRY_AREA_BASE) + (CPU_ENTRY_AREA_PER_CPU + CPU_ENTRY_AREA_ARRAY_SIZE - CPU_ENTRY_AREA_BASE)
extern struct cpu_entry_area *get_cpu_entry_area(int cpu);
--- a/arch/x86/include/asm/pgtable_32_types.h +++ b/arch/x86/include/asm/pgtable_32_types.h @@ -44,11 +44,11 @@ extern bool __vmalloc_start_set; /* set * Define this here and validate with BUILD_BUG_ON() in pgtable_32.c * to avoid include recursion hell */ -#define CPU_ENTRY_AREA_PAGES (NR_CPUS * 40) +#define CPU_ENTRY_AREA_PAGES (NR_CPUS * 39)
-#define CPU_ENTRY_AREA_BASE \ - ((FIXADDR_TOT_START - PAGE_SIZE * (CPU_ENTRY_AREA_PAGES + 1)) \ - & PMD_MASK) +/* The +1 is for the readonly IDT page: */ +#define CPU_ENTRY_AREA_BASE \ + ((FIXADDR_TOT_START - PAGE_SIZE*(CPU_ENTRY_AREA_PAGES+1)) & PMD_MASK)
#define LDT_BASE_ADDR \ ((CPU_ENTRY_AREA_BASE - PAGE_SIZE) & PMD_MASK) --- a/arch/x86/mm/cpu_entry_area.c +++ b/arch/x86/mm/cpu_entry_area.c @@ -178,7 +178,9 @@ static __init void setup_cpu_entry_area_ #ifdef CONFIG_X86_32 unsigned long start, end;
- BUILD_BUG_ON(CPU_ENTRY_AREA_PAGES * PAGE_SIZE < CPU_ENTRY_AREA_MAP_SIZE); + /* The +1 is for the readonly IDT: */ + BUILD_BUG_ON((CPU_ENTRY_AREA_PAGES+1)*PAGE_SIZE != CPU_ENTRY_AREA_MAP_SIZE); + BUILD_BUG_ON(CPU_ENTRY_AREA_TOTAL_SIZE != CPU_ENTRY_AREA_MAP_SIZE); BUG_ON(CPU_ENTRY_AREA_BASE & ~PMD_MASK);
start = CPU_ENTRY_AREA_BASE;
From: Andy Lutomirski luto@kernel.org
commit 4a13b0e3e10996b9aa0b45a764ecfe49f6fcd360 upstream.
UNWIND_ESPFIX_STACK needs to read the GDT, and the GDT mapping that can be accessed via %fs is not mapped in the user pagetables. Use SGDT to find the cpu_entry_area mapping and read the espfix offset from that instead.
Reported-and-tested-by: Borislav Petkov bp@alien8.de Signed-off-by: Andy Lutomirski luto@kernel.org Cc: Peter Zijlstra peterz@infradead.org Cc: Thomas Gleixner tglx@linutronix.de Cc: Linus Torvalds torvalds@linux-foundation.org Cc: stable@vger.kernel.org Signed-off-by: Ingo Molnar mingo@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/x86/entry/entry_32.S | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-)
--- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -415,7 +415,8 @@
.macro CHECK_AND_APPLY_ESPFIX #ifdef CONFIG_X86_ESPFIX32 -#define GDT_ESPFIX_SS PER_CPU_VAR(gdt_page) + (GDT_ENTRY_ESPFIX_SS * 8) +#define GDT_ESPFIX_OFFSET (GDT_ENTRY_ESPFIX_SS * 8) +#define GDT_ESPFIX_SS PER_CPU_VAR(gdt_page) + GDT_ESPFIX_OFFSET
ALTERNATIVE "jmp .Lend_@", "", X86_BUG_ESPFIX
@@ -1147,12 +1148,26 @@ ENDPROC(entry_INT80_32) * We can't call C functions using the ESPFIX stack. This code reads * the high word of the segment base from the GDT and swiches to the * normal stack and adjusts ESP with the matching offset. + * + * We might be on user CR3 here, so percpu data is not mapped and we can't + * access the GDT through the percpu segment. Instead, use SGDT to find + * the cpu_entry_area alias of the GDT. */ #ifdef CONFIG_X86_ESPFIX32 /* fixup the stack */ - mov GDT_ESPFIX_SS + 4, %al /* bits 16..23 */ - mov GDT_ESPFIX_SS + 7, %ah /* bits 24..31 */ + pushl %ecx + subl $2*4, %esp + sgdt (%esp) + movl 2(%esp), %ecx /* GDT address */ + /* + * Careful: ECX is a linear pointer, so we need to force base + * zero. %cs is the only known-linear segment we have right now. + */ + mov %cs:GDT_ESPFIX_OFFSET + 4(%ecx), %al /* bits 16..23 */ + mov %cs:GDT_ESPFIX_OFFSET + 7(%ecx), %ah /* bits 24..31 */ shl $16, %eax + addl $2*4, %esp + popl %ecx addl %esp, %eax /* the adjusted stack pointer */ pushl $__KERNEL_DS pushl %eax
From: Yang Tao yang.tao172@zte.com.cn
commit ca16d5bee59807bf04deaab0a8eccecd5061528c upstream.
Robust futexes utilize the robust_list mechanism to allow the kernel to release futexes which are held when a task exits. The exit can be voluntary or caused by a signal or fault. This prevents that waiters block forever.
The futex operations in user space store a pointer to the futex they are either locking or unlocking in the op_pending member of the per task robust list.
After a lock operation has succeeded the futex is queued in the robust list linked list and the op_pending pointer is cleared.
After an unlock operation has succeeded the futex is removed from the robust list linked list and the op_pending pointer is cleared.
The robust list exit code checks for the pending operation and any futex which is queued in the linked list. It carefully checks whether the futex value is the TID of the exiting task. If so, it sets the OWNER_DIED bit and tries to wake up a potential waiter.
This is race free for the lock operation but unlock has two race scenarios where waiters might not be woken up. These issues can be observed with regular robust pthread mutexes. PI aware pthread mutexes are not affected.
(1) Unlocking task is killed after unlocking the futex value in user space before being able to wake a waiter.
pthread_mutex_unlock() | V atomic_exchange_rel (&mutex->__data.__lock, 0) <------------------------killed lll_futex_wake () | | |(__lock = 0) |(enter kernel) | V do_exit() exit_mm() mm_release() exit_robust_list() handle_futex_death() | |(__lock = 0) |(uval = 0) | V if ((uval & FUTEX_TID_MASK) != task_pid_vnr(curr)) return 0;
The sanity check which ensures that the user space futex is owned by the exiting task prevents the wakeup of waiters which in consequence block infinitely.
(2) Waiting task is killed after a wakeup and before it can acquire the futex in user space.
OWNER WAITER futex_wait() pthread_mutex_unlock() | | | |(__lock = 0) | | | V | futex_wake() ------------> wakeup() | |(return to userspace) |(__lock = 0) | V oldval = mutex->__data.__lock <-----------------killed atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, | id | assume_other_futex_waiters, 0) | | | (enter kernel)| | V do_exit() | | V handle_futex_death() | |(__lock = 0) |(uval = 0) | V if ((uval & FUTEX_TID_MASK) != task_pid_vnr(curr)) return 0;
The sanity check which ensures that the user space futex is owned by the exiting task prevents the wakeup of waiters, which seems to be correct as the exiting task does not own the futex value, but the consequence is that other waiters wont be woken up and block infinitely.
In both scenarios the following conditions are true:
- task->robust_list->list_op_pending != NULL - user space futex value == 0 - Regular futex (not PI)
If these conditions are met then it is reasonably safe to wake up a potential waiter in order to prevent the above problems.
As this might be a false positive it can cause spurious wakeups, but the waiter side has to handle other types of unrelated wakeups, e.g. signals gracefully anyway. So such a spurious wakeup will not affect the correctness of these operations.
This workaround must not touch the user space futex value and cannot set the OWNER_DIED bit because the lock value is 0, i.e. uncontended. Setting OWNER_DIED in this case would result in inconsistent state and subsequently in malfunction of the owner died handling in user space.
The rest of the user space state is still consistent as no other task can observe the list_op_pending entry in the exiting tasks robust list.
The eventually woken up waiter will observe the uncontended lock value and take it over.
[ tglx: Massaged changelog and comment. Made the return explicit and not depend on the subsequent check and added constants to hand into handle_futex_death() instead of plain numbers. Fixed a few coding style issues. ]
Fixes: 0771dfefc9e5 ("[PATCH] lightweight robust futexes: core") Signed-off-by: Yang Tao yang.tao172@zte.com.cn Signed-off-by: Yi Wang wang.yi59@zte.com.cn Signed-off-by: Thomas Gleixner tglx@linutronix.de Reviewed-by: Ingo Molnar mingo@kernel.org Acked-by: Peter Zijlstra (Intel) peterz@infradead.org Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/1573010582-35297-1-git-send-email-wang.yi59@zte.co... Link: https://lkml.kernel.org/r/20191106224555.943191378@linutronix.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- kernel/futex.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 7 deletions(-)
--- a/kernel/futex.c +++ b/kernel/futex.c @@ -3454,11 +3454,16 @@ err_unlock: return ret; }
+/* Constants for the pending_op argument of handle_futex_death */ +#define HANDLE_DEATH_PENDING true +#define HANDLE_DEATH_LIST false + /* * Process a futex-list entry, check whether it's owned by the * dying task, and do notification if so: */ -static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, int pi) +static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, + bool pi, bool pending_op) { u32 uval, uninitialized_var(nval), mval; int err; @@ -3471,6 +3476,42 @@ retry: if (get_user(uval, uaddr)) return -1;
+ /* + * Special case for regular (non PI) futexes. The unlock path in + * user space has two race scenarios: + * + * 1. The unlock path releases the user space futex value and + * before it can execute the futex() syscall to wake up + * waiters it is killed. + * + * 2. A woken up waiter is killed before it can acquire the + * futex in user space. + * + * In both cases the TID validation below prevents a wakeup of + * potential waiters which can cause these waiters to block + * forever. + * + * In both cases the following conditions are met: + * + * 1) task->robust_list->list_op_pending != NULL + * @pending_op == true + * 2) User space futex value == 0 + * 3) Regular futex: @pi == false + * + * If these conditions are met, it is safe to attempt waking up a + * potential waiter without touching the user space futex value and + * trying to set the OWNER_DIED bit. The user space futex value is + * uncontended and the rest of the user space mutex state is + * consistent, so a woken waiter will just take over the + * uncontended futex. Setting the OWNER_DIED bit would create + * inconsistent state and malfunction of the user space owner died + * handling. + */ + if (pending_op && !pi && !uval) { + futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY); + return 0; + } + if ((uval & FUTEX_TID_MASK) != task_pid_vnr(curr)) return 0;
@@ -3590,10 +3631,11 @@ void exit_robust_list(struct task_struct * A pending lock might already be on the list, so * don't process it twice: */ - if (entry != pending) + if (entry != pending) { if (handle_futex_death((void __user *)entry + futex_offset, - curr, pi)) + curr, pi, HANDLE_DEATH_LIST)) return; + } if (rc) return; entry = next_entry; @@ -3607,9 +3649,10 @@ void exit_robust_list(struct task_struct cond_resched(); }
- if (pending) + if (pending) { handle_futex_death((void __user *)pending + futex_offset, - curr, pip); + curr, pip, HANDLE_DEATH_PENDING); + } }
long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, @@ -3786,7 +3829,8 @@ void compat_exit_robust_list(struct task if (entry != pending) { void __user *uaddr = futex_uaddr(entry, futex_offset);
- if (handle_futex_death(uaddr, curr, pi)) + if (handle_futex_death(uaddr, curr, pi, + HANDLE_DEATH_LIST)) return; } if (rc) @@ -3805,7 +3849,7 @@ void compat_exit_robust_list(struct task if (pending) { void __user *uaddr = futex_uaddr(pending, futex_offset);
- handle_futex_death(uaddr, curr, pip); + handle_futex_death(uaddr, curr, pip, HANDLE_DEATH_PENDING); } }
From: Takashi Iwai tiwai@suse.de
commit 9435f2bb66874a0c4dd25e7c978957a7ca2c93b1 upstream.
snd_usb_mixer_controls_badd() that parses UAC3 BADD profiles misses a NULL check for the given interfaces. When a malformed USB descriptor is passed, this may lead to an Oops, as spotted by syzkaller. Skip the iteration if the interface doesn't exist for avoiding the crash.
Fixes: 17156f23e93c ("ALSA: usb: add UAC3 BADD profiles support") Reported-by: syzbot+a36ab65c6653d7ccdd62@syzkaller.appspotmail.com Suggested-by: Dan Carpenter dan.carpenter@oracle.com Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20191122112840.24797-1-tiwai@suse.de Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- sound/usb/mixer.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -2930,6 +2930,9 @@ static int snd_usb_mixer_controls_badd(s continue;
iface = usb_ifnum_to_if(dev, intf); + if (!iface) + continue; + num = iface->num_altsetting;
if (num < 2)
From: Oliver Neukum oneukum@suse.com
commit 5f9f0b11f0816b35867f2cf71e54d95f53f03902 upstream.
If starting the transfer of a command suceeds but the transfer for the reply fails, it is not enough to initiate killing the transfer for the command may still be running. You need to wait for the killing to finish before you can reuse URB and buffer.
Reported-and-tested-by: syzbot+711468aa5c3a1eabf863@syzkaller.appspotmail.com Signed-off-by: Oliver Neukum oneukum@suse.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/nfc/port100.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/nfc/port100.c +++ b/drivers/nfc/port100.c @@ -783,7 +783,7 @@ static int port100_send_frame_async(stru
rc = port100_submit_urb_for_ack(dev, GFP_KERNEL); if (rc) - usb_unlink_urb(dev->out_urb); + usb_kill_urb(dev->out_urb);
exit: mutex_unlock(&dev->out_urb_lock);
From: Jouni Hogander jouni.hogander@unikie.com
commit b8eb718348b8fb30b5a7d0a8fce26fb3f4ac741b upstream.
kobject_init_and_add takes reference even when it fails. This has to be given up by the caller in error handling. Otherwise memory allocated by kobject_init_and_add is never freed. Originally found by Syzkaller:
BUG: memory leak unreferenced object 0xffff8880679f8b08 (size 8): comm "netdev_register", pid 269, jiffies 4294693094 (age 12.132s) hex dump (first 8 bytes): 72 78 2d 30 00 36 20 d4 rx-0.6 . backtrace: [<000000008c93818e>] __kmalloc_track_caller+0x16e/0x290 [<000000001f2e4e49>] kvasprintf+0xb1/0x140 [<000000007f313394>] kvasprintf_const+0x56/0x160 [<00000000aeca11c8>] kobject_set_name_vargs+0x5b/0x140 [<0000000073a0367c>] kobject_init_and_add+0xd8/0x170 [<0000000088838e4b>] net_rx_queue_update_kobjects+0x152/0x560 [<000000006be5f104>] netdev_register_kobject+0x210/0x380 [<00000000e31dab9d>] register_netdevice+0xa1b/0xf00 [<00000000f68b2465>] __tun_chr_ioctl+0x20d5/0x3dd0 [<000000004c50599f>] tun_chr_ioctl+0x2f/0x40 [<00000000bbd4c317>] do_vfs_ioctl+0x1c7/0x1510 [<00000000d4c59e8f>] ksys_ioctl+0x99/0xb0 [<00000000946aea81>] __x64_sys_ioctl+0x78/0xb0 [<0000000038d946e5>] do_syscall_64+0x16f/0x580 [<00000000e0aa5d8f>] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [<00000000285b3d1a>] 0xffffffffffffffff
Cc: David Miller davem@davemloft.net Cc: Lukas Bulwahn lukas.bulwahn@gmail.com Signed-off-by: Jouni Hogander jouni.hogander@unikie.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- net/core/net-sysfs.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-)
--- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -923,21 +923,23 @@ static int rx_queue_add_kobject(struct n error = kobject_init_and_add(kobj, &rx_queue_ktype, NULL, "rx-%u", index); if (error) - return error; + goto err;
dev_hold(queue->dev);
if (dev->sysfs_rx_queue_group) { error = sysfs_create_group(kobj, dev->sysfs_rx_queue_group); - if (error) { - kobject_put(kobj); - return error; - } + if (error) + goto err; }
kobject_uevent(kobj, KOBJ_ADD);
return error; + +err: + kobject_put(kobj); + return error; } #endif /* CONFIG_SYSFS */
@@ -1461,21 +1463,21 @@ static int netdev_queue_add_kobject(stru error = kobject_init_and_add(kobj, &netdev_queue_ktype, NULL, "tx-%u", index); if (error) - return error; + goto err;
dev_hold(queue->dev);
#ifdef CONFIG_BQL error = sysfs_create_group(kobj, &dql_group); - if (error) { - kobject_put(kobj); - return error; - } + if (error) + goto err; #endif
kobject_uevent(kobj, KOBJ_ADD);
- return 0; +err: + kobject_put(kobj); + return error; } #endif /* CONFIG_SYSFS */
From: Vandana BN bnvandana@gmail.com
commit b4add02d2236fd5f568db141cfd8eb4290972eb3 upstream.
When vbi stream is started, followed by video streaming, the vid_cap_streaming and vid_out_streaming were not being set to true, which would cause the video stream to stop when vbi stream is stopped. This patch allows to set vid_cap_streaming and vid_out_streaming to true. According to Hans Verkuil it appears that these 'if (dev->kthread_vid_cap)' checks are a left-over from the original vivid development and should never have been there.
Signed-off-by: Vandana BN bnvandana@gmail.com Cc: stable@vger.kernel.org # for v3.18 and up Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+samsung@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/media/platform/vivid/vivid-vid-cap.c | 3 --- drivers/media/platform/vivid/vivid-vid-out.c | 3 --- 2 files changed, 6 deletions(-)
--- a/drivers/media/platform/vivid/vivid-vid-cap.c +++ b/drivers/media/platform/vivid/vivid-vid-cap.c @@ -223,9 +223,6 @@ static int vid_cap_start_streaming(struc if (vb2_is_streaming(&dev->vb_vid_out_q)) dev->can_loop_video = vivid_vid_can_loop(dev);
- if (dev->kthread_vid_cap) - return 0; - dev->vid_cap_seq_count = 0; dprintk(dev, 1, "%s\n", __func__); for (i = 0; i < VIDEO_MAX_FRAME; i++) --- a/drivers/media/platform/vivid/vivid-vid-out.c +++ b/drivers/media/platform/vivid/vivid-vid-out.c @@ -161,9 +161,6 @@ static int vid_out_start_streaming(struc if (vb2_is_streaming(&dev->vb_vid_cap_q)) dev->can_loop_video = vivid_vid_can_loop(dev);
- if (dev->kthread_vid_out) - return 0; - dev->vid_out_seq_count = 0; dprintk(dev, 1, "%s\n", __func__); if (dev->start_streaming_error) {
From: Alexander Popov alex.popov@linux.com
commit 6dcd5d7a7a29c1e4b8016a06aed78cd650cd8c27 upstream.
There is the same incorrect approach to locking implemented in vivid_stop_generating_vid_cap(), vivid_stop_generating_vid_out() and sdr_cap_stop_streaming().
These functions are called during streaming stopping with vivid_dev.mutex locked. And they all do the same mistake while stopping their kthreads, which need to lock this mutex as well. See the example from vivid_stop_generating_vid_cap(): /* shutdown control thread */ vivid_grab_controls(dev, false); mutex_unlock(&dev->mutex); kthread_stop(dev->kthread_vid_cap); dev->kthread_vid_cap = NULL; mutex_lock(&dev->mutex);
But when this mutex is unlocked, another vb2_fop_read() can lock it instead of vivid_thread_vid_cap() and manipulate the buffer queue. That causes a use-after-free access later.
To fix those issues let's: 1. avoid unlocking the mutex in vivid_stop_generating_vid_cap(), vivid_stop_generating_vid_out() and sdr_cap_stop_streaming(); 2. use mutex_trylock() with schedule_timeout_uninterruptible() in the loops of the vivid kthread handlers.
Signed-off-by: Alexander Popov alex.popov@linux.com Acked-by: Linus Torvalds torvalds@linux-foundation.org Tested-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Cc: stable@vger.kernel.org # for v3.18 and up Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/media/platform/vivid/vivid-kthread-cap.c | 8 +++++--- drivers/media/platform/vivid/vivid-kthread-out.c | 8 +++++--- drivers/media/platform/vivid/vivid-sdr-cap.c | 8 +++++--- 3 files changed, 15 insertions(+), 9 deletions(-)
--- a/drivers/media/platform/vivid/vivid-kthread-cap.c +++ b/drivers/media/platform/vivid/vivid-kthread-cap.c @@ -796,7 +796,11 @@ static int vivid_thread_vid_cap(void *da if (kthread_should_stop()) break;
- mutex_lock(&dev->mutex); + if (!mutex_trylock(&dev->mutex)) { + schedule_timeout_uninterruptible(1); + continue; + } + cur_jiffies = jiffies; if (dev->cap_seq_resync) { dev->jiffies_vid_cap = cur_jiffies; @@ -956,8 +960,6 @@ void vivid_stop_generating_vid_cap(struc
/* shutdown control thread */ vivid_grab_controls(dev, false); - mutex_unlock(&dev->mutex); kthread_stop(dev->kthread_vid_cap); dev->kthread_vid_cap = NULL; - mutex_lock(&dev->mutex); } --- a/drivers/media/platform/vivid/vivid-kthread-out.c +++ b/drivers/media/platform/vivid/vivid-kthread-out.c @@ -143,7 +143,11 @@ static int vivid_thread_vid_out(void *da if (kthread_should_stop()) break;
- mutex_lock(&dev->mutex); + if (!mutex_trylock(&dev->mutex)) { + schedule_timeout_uninterruptible(1); + continue; + } + cur_jiffies = jiffies; if (dev->out_seq_resync) { dev->jiffies_vid_out = cur_jiffies; @@ -301,8 +305,6 @@ void vivid_stop_generating_vid_out(struc
/* shutdown control thread */ vivid_grab_controls(dev, false); - mutex_unlock(&dev->mutex); kthread_stop(dev->kthread_vid_out); dev->kthread_vid_out = NULL; - mutex_lock(&dev->mutex); } --- a/drivers/media/platform/vivid/vivid-sdr-cap.c +++ b/drivers/media/platform/vivid/vivid-sdr-cap.c @@ -141,7 +141,11 @@ static int vivid_thread_sdr_cap(void *da if (kthread_should_stop()) break;
- mutex_lock(&dev->mutex); + if (!mutex_trylock(&dev->mutex)) { + schedule_timeout_uninterruptible(1); + continue; + } + cur_jiffies = jiffies; if (dev->sdr_cap_seq_resync) { dev->jiffies_sdr_cap = cur_jiffies; @@ -303,10 +307,8 @@ static void sdr_cap_stop_streaming(struc }
/* shutdown control thread */ - mutex_unlock(&dev->mutex); kthread_stop(dev->kthread_sdr_cap); dev->kthread_sdr_cap = NULL; - mutex_lock(&dev->mutex); }
static void sdr_cap_buf_request_complete(struct vb2_buffer *vb)
From: Alan Stern stern@rowland.harvard.edu
commit c7a191464078262bf799136317c95824e26a222b upstream.
The syzbot fuzzer found two invalid-access bugs in the usbvision driver. These bugs occur when userspace keeps the device file open after the device has been disconnected and usbvision_disconnect() has set usbvision->dev to NULL:
When the device file is closed, usbvision_radio_close() tries to issue a usb_set_interface() call, passing the NULL pointer as its first argument.
If userspace performs a querycap ioctl call, vidioc_querycap() calls usb_make_path() with the same NULL pointer.
This patch fixes the problems by making the appropriate tests beforehand. Note that vidioc_querycap() is protected by usbvision->v4l2_lock, acquired in a higher layer of the V4L2 subsystem.
Reported-and-tested-by: syzbot+7fa38a608b1075dfd634@syzkaller.appspotmail.com
Signed-off-by: Alan Stern stern@rowland.harvard.edu CC: stable@vger.kernel.org Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+samsung@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/media/usb/usbvision/usbvision-video.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
--- a/drivers/media/usb/usbvision/usbvision-video.c +++ b/drivers/media/usb/usbvision/usbvision-video.c @@ -453,6 +453,9 @@ static int vidioc_querycap(struct file * { struct usb_usbvision *usbvision = video_drvdata(file);
+ if (!usbvision->dev) + return -ENODEV; + strscpy(vc->driver, "USBVision", sizeof(vc->driver)); strscpy(vc->card, usbvision_device_data[usbvision->dev_model].model_string, @@ -1111,8 +1114,9 @@ static int usbvision_radio_close(struct mutex_lock(&usbvision->v4l2_lock); /* Set packet size to 0 */ usbvision->iface_alt = 0; - usb_set_interface(usbvision->dev, usbvision->iface, - usbvision->iface_alt); + if (usbvision->dev) + usb_set_interface(usbvision->dev, usbvision->iface, + usbvision->iface_alt);
usbvision_audio_off(usbvision); usbvision->radio = 0;
From: Alan Stern stern@rowland.harvard.edu
commit 9e08117c9d4efc1e1bc6fce83dab856d9fd284b6 upstream.
Visual inspection of the usbvision driver shows that it suffers from three races between its open, close, and disconnect handlers. In particular, the driver is careful to update its usbvision->user and usbvision->remove_pending flags while holding the private mutex, but:
usbvision_v4l2_close() and usbvision_radio_close() don't hold the mutex while they check the value of usbvision->remove_pending;
usbvision_disconnect() doesn't hold the mutex while checking the value of usbvision->user; and
also, usbvision_v4l2_open() and usbvision_radio_open() don't check whether the device has been unplugged before allowing the user to open the device files.
Each of these can potentially lead to usbvision_release() being called twice and use-after-free errors.
This patch fixes the races by reading the flags while the mutex is still held and checking for pending removes before allowing an open to succeed.
Signed-off-by: Alan Stern stern@rowland.harvard.edu CC: stable@vger.kernel.org Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+samsung@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/media/usb/usbvision/usbvision-video.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-)
--- a/drivers/media/usb/usbvision/usbvision-video.c +++ b/drivers/media/usb/usbvision/usbvision-video.c @@ -314,6 +314,10 @@ static int usbvision_v4l2_open(struct fi if (mutex_lock_interruptible(&usbvision->v4l2_lock)) return -ERESTARTSYS;
+ if (usbvision->remove_pending) { + err_code = -ENODEV; + goto unlock; + } if (usbvision->user) { err_code = -EBUSY; } else { @@ -377,6 +381,7 @@ unlock: static int usbvision_v4l2_close(struct file *file) { struct usb_usbvision *usbvision = video_drvdata(file); + int r;
PDEBUG(DBG_IO, "close");
@@ -391,9 +396,10 @@ static int usbvision_v4l2_close(struct f usbvision_scratch_free(usbvision);
usbvision->user--; + r = usbvision->remove_pending; mutex_unlock(&usbvision->v4l2_lock);
- if (usbvision->remove_pending) { + if (r) { printk(KERN_INFO "%s: Final disconnect\n", __func__); usbvision_release(usbvision); return 0; @@ -1076,6 +1082,11 @@ static int usbvision_radio_open(struct f
if (mutex_lock_interruptible(&usbvision->v4l2_lock)) return -ERESTARTSYS; + + if (usbvision->remove_pending) { + err_code = -ENODEV; + goto out; + } err_code = v4l2_fh_open(file); if (err_code) goto out; @@ -1108,6 +1119,7 @@ out: static int usbvision_radio_close(struct file *file) { struct usb_usbvision *usbvision = video_drvdata(file); + int r;
PDEBUG(DBG_IO, "");
@@ -1121,9 +1133,10 @@ static int usbvision_radio_close(struct usbvision_audio_off(usbvision); usbvision->radio = 0; usbvision->user--; + r = usbvision->remove_pending; mutex_unlock(&usbvision->v4l2_lock);
- if (usbvision->remove_pending) { + if (r) { printk(KERN_INFO "%s: Final disconnect\n", __func__); v4l2_fh_release(file); usbvision_release(usbvision); @@ -1555,6 +1568,7 @@ err_usb: static void usbvision_disconnect(struct usb_interface *intf) { struct usb_usbvision *usbvision = to_usbvision(usb_get_intfdata(intf)); + int u;
PDEBUG(DBG_PROBE, "");
@@ -1571,13 +1585,14 @@ static void usbvision_disconnect(struct v4l2_device_disconnect(&usbvision->v4l2_dev); usbvision_i2c_unregister(usbvision); usbvision->remove_pending = 1; /* Now all ISO data will be ignored */ + u = usbvision->user;
usb_put_dev(usbvision->dev); usbvision->dev = NULL; /* USB device is no more */
mutex_unlock(&usbvision->v4l2_lock);
- if (usbvision->user) { + if (u) { printk(KERN_INFO "%s: In use, disconnect pending\n", __func__); wake_up_interruptible(&usbvision->wait_frame);
From: Kai Shen shenkai8@huawei.com
commit e6e8df07268c1f75dd9215536e2ce4587b70f977 upstream.
Add NULL checks to show() and store() in cpufreq.c to avoid attempts to invoke a NULL callback.
Though some interfaces of cpufreq are set as read-only, users can still get write permission using chmod which can lead to a kernel crash, as follows:
chmod +w /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq echo 1 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
This bug was found in linux 4.19.
Signed-off-by: Kai Shen shenkai8@huawei.com Reported-by: Feilong Lin linfeilong@huawei.com Reviewed-by: Feilong Lin linfeilong@huawei.com Acked-by: Viresh Kumar viresh.kumar@linaro.org [ rjw: Subject & changelog ] Cc: All applicable stable@vger.kernel.org Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/cpufreq/cpufreq.c | 6 ++++++ 1 file changed, 6 insertions(+)
--- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -933,6 +933,9 @@ static ssize_t show(struct kobject *kobj struct freq_attr *fattr = to_attr(attr); ssize_t ret;
+ if (!fattr->show) + return -EIO; + down_read(&policy->rwsem); ret = fattr->show(policy, buf); up_read(&policy->rwsem); @@ -947,6 +950,9 @@ static ssize_t store(struct kobject *kob struct freq_attr *fattr = to_attr(attr); ssize_t ret = -EINVAL;
+ if (!fattr->store) + return -EIO; + /* * cpus_read_trylock() is used here to work around a circular lock * dependency problem with respect to the cpufreq_register_driver().
From: Laurent Pinchart laurent.pinchart@ideasonboard.com
commit 8c279e9394cade640ed86ec6c6645a0e7df5e0b6 upstream.
When parsing the UVC control descriptors fails, the error path tries to cleanup a media device that hasn't been initialised, potentially resulting in a crash. Fix this by initialising the media device before the error handling path can be reached.
Fixes: 5a254d751e52 ("[media] uvcvideo: Register a v4l2_device") Reported-by: syzbot+c86454eb3af9e8a4da20@syzkaller.appspotmail.com Signed-off-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Mauro Carvalho Chehab mchehab+samsung@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/media/usb/uvc/uvc_driver.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-)
--- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -2151,6 +2151,20 @@ static int uvc_probe(struct usb_interfac sizeof(dev->name) - len); }
+ /* Initialize the media device. */ +#ifdef CONFIG_MEDIA_CONTROLLER + dev->mdev.dev = &intf->dev; + strscpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model)); + if (udev->serial) + strscpy(dev->mdev.serial, udev->serial, + sizeof(dev->mdev.serial)); + usb_make_path(udev, dev->mdev.bus_info, sizeof(dev->mdev.bus_info)); + dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); + media_device_init(&dev->mdev); + + dev->vdev.mdev = &dev->mdev; +#endif + /* Parse the Video Class control descriptor. */ if (uvc_parse_control(dev) < 0) { uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC " @@ -2171,19 +2185,7 @@ static int uvc_probe(struct usb_interfac "linux-uvc-devel mailing list.\n"); }
- /* Initialize the media device and register the V4L2 device. */ -#ifdef CONFIG_MEDIA_CONTROLLER - dev->mdev.dev = &intf->dev; - strscpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model)); - if (udev->serial) - strscpy(dev->mdev.serial, udev->serial, - sizeof(dev->mdev.serial)); - usb_make_path(udev, dev->mdev.bus_info, sizeof(dev->mdev.bus_info)); - dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); - media_device_init(&dev->mdev); - - dev->vdev.mdev = &dev->mdev; -#endif + /* Register the V4L2 device. */ if (v4l2_device_register(&intf->dev, &dev->vdev) < 0) goto error;
From: Oliver Neukum oneukum@suse.com
commit 1b976fc6d684e3282914cdbe7a8d68fdce19095c upstream.
The driver needs an isochronous endpoint to be present. It will oops in its absence. Add checking for it.
Reported-by: syzbot+d93dff37e6a89431c158@syzkaller.appspotmail.com Signed-off-by: Oliver Neukum oneukum@suse.com Signed-off-by: Sean Young sean@mess.org Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/media/usb/b2c2/flexcop-usb.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/drivers/media/usb/b2c2/flexcop-usb.c +++ b/drivers/media/usb/b2c2/flexcop-usb.c @@ -538,6 +538,9 @@ static int flexcop_usb_probe(struct usb_ struct flexcop_device *fc = NULL; int ret;
+ if (intf->cur_altsetting->desc.bNumEndpoints < 1) + return -ENODEV; + if ((fc = flexcop_device_kmalloc(sizeof(struct flexcop_usb))) == NULL) { err("out of memory\n"); return -ENOMEM;
From: Vito Caputo vcaputo@pengaru.com
commit ca8f245f284eeffa56f3b7a5eb6fc503159ee028 upstream.
Don't use uninitialized ircode[] in cxusb_rc_query() when cxusb_ctrl_msg() fails to populate its contents.
syzbot reported:
dvb-usb: bulk message failed: -22 (1/-30591) ===================================================== BUG: KMSAN: uninit-value in ir_lookup_by_scancode drivers/media/rc/rc-main.c:494 [inline] BUG: KMSAN: uninit-value in rc_g_keycode_from_table drivers/media/rc/rc-main.c:582 [inline] BUG: KMSAN: uninit-value in rc_keydown+0x1a6/0x6f0 drivers/media/rc/rc-main.c:816 CPU: 1 PID: 11436 Comm: kworker/1:2 Not tainted 5.3.0-rc7+ #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Workqueue: events dvb_usb_read_remote_control Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x191/0x1f0 lib/dump_stack.c:113 kmsan_report+0x13a/0x2b0 mm/kmsan/kmsan_report.c:108 __msan_warning+0x73/0xe0 mm/kmsan/kmsan_instr.c:250 bsearch+0x1dd/0x250 lib/bsearch.c:41 ir_lookup_by_scancode drivers/media/rc/rc-main.c:494 [inline] rc_g_keycode_from_table drivers/media/rc/rc-main.c:582 [inline] rc_keydown+0x1a6/0x6f0 drivers/media/rc/rc-main.c:816 cxusb_rc_query+0x2e1/0x360 drivers/media/usb/dvb-usb/cxusb.c:548 dvb_usb_read_remote_control+0xf9/0x290 drivers/media/usb/dvb-usb/dvb-usb-remote.c:261 process_one_work+0x1572/0x1ef0 kernel/workqueue.c:2269 worker_thread+0x111b/0x2460 kernel/workqueue.c:2415 kthread+0x4b5/0x4f0 kernel/kthread.c:256 ret_from_fork+0x35/0x40 arch/x86/entry/entry_64.S:355
Uninit was stored to memory at: kmsan_save_stack_with_flags mm/kmsan/kmsan.c:150 [inline] kmsan_internal_chain_origin+0xd2/0x170 mm/kmsan/kmsan.c:314 __msan_chain_origin+0x6b/0xe0 mm/kmsan/kmsan_instr.c:184 rc_g_keycode_from_table drivers/media/rc/rc-main.c:583 [inline] rc_keydown+0x2c4/0x6f0 drivers/media/rc/rc-main.c:816 cxusb_rc_query+0x2e1/0x360 drivers/media/usb/dvb-usb/cxusb.c:548 dvb_usb_read_remote_control+0xf9/0x290 drivers/media/usb/dvb-usb/dvb-usb-remote.c:261 process_one_work+0x1572/0x1ef0 kernel/workqueue.c:2269 worker_thread+0x111b/0x2460 kernel/workqueue.c:2415 kthread+0x4b5/0x4f0 kernel/kthread.c:256 ret_from_fork+0x35/0x40 arch/x86/entry/entry_64.S:355
Local variable description: ----ircode@cxusb_rc_query Variable was created at: cxusb_rc_query+0x4d/0x360 drivers/media/usb/dvb-usb/cxusb.c:543 dvb_usb_read_remote_control+0xf9/0x290 drivers/media/usb/dvb-usb/dvb-usb-remote.c:261
Signed-off-by: Vito Caputo vcaputo@pengaru.com Reported-by: syzbot syzkaller@googlegroups.com Signed-off-by: Sean Young sean@mess.org Signed-off-by: Mauro Carvalho Chehab mchehab+samsung@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/media/usb/dvb-usb/cxusb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/media/usb/dvb-usb/cxusb.c +++ b/drivers/media/usb/dvb-usb/cxusb.c @@ -542,7 +542,8 @@ static int cxusb_rc_query(struct dvb_usb { u8 ircode[4];
- cxusb_ctrl_msg(d, CMD_GET_IR_CODE, NULL, 0, ircode, 4); + if (cxusb_ctrl_msg(d, CMD_GET_IR_CODE, NULL, 0, ircode, 4) < 0) + return 0;
if (ircode[2] || ircode[3]) rc_keydown(d->rc_dev, RC_PROTO_NEC,
From: Sean Young sean@mess.org
commit f3f5ba42c58d56d50f539854d8cc188944e96087 upstream.
The touch timer is set up in intf1. If the second interface does not exist, the timer and touch input device are not setup and we get the following error, when touch events are reported via intf0.
kernel BUG at kernel/time/timer.c:956! invalid opcode: 0000 [#1] SMP KASAN CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.4.0-rc1+ #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 RIP: 0010:__mod_timer kernel/time/timer.c:956 [inline] RIP: 0010:__mod_timer kernel/time/timer.c:949 [inline] RIP: 0010:mod_timer+0x5a2/0xb50 kernel/time/timer.c:1100 Code: 45 10 c7 44 24 14 ff ff ff ff 48 89 44 24 08 48 8d 45 20 48 c7 44 24 18 00 00 00 00 48 89 04 24 e9 5a fc ff ff e8 ae ce 0e 00 <0f> 0b e8 a7 ce 0e 00 4c 89 74 24 20 e9 37 fe ff ff e8 98 ce 0e 00 RSP: 0018:ffff8881db209930 EFLAGS: 00010006 RAX: ffffffff86c2b200 RBX: 00000000ffffa688 RCX: ffffffff83efc583 RDX: 0000000000000100 RSI: ffffffff812f4d82 RDI: ffff8881d2356200 RBP: ffff8881d23561e8 R08: ffffffff86c2b200 R09: ffffed103a46abeb R10: ffffed103a46abea R11: ffff8881d2355f53 R12: dffffc0000000000 R13: 1ffff1103b64132d R14: ffff8881d2355f50 R15: 0000000000000006 FS: 0000000000000000(0000) GS:ffff8881db200000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f75e2799000 CR3: 00000001d3b07000 CR4: 00000000001406f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: <IRQ> imon_touch_event drivers/media/rc/imon.c:1348 [inline] imon_incoming_packet.isra.0+0x2546/0x2f10 drivers/media/rc/imon.c:1603 usb_rx_callback_intf0+0x151/0x1e0 drivers/media/rc/imon.c:1734 __usb_hcd_giveback_urb+0x1f2/0x470 drivers/usb/core/hcd.c:1654 usb_hcd_giveback_urb+0x368/0x420 drivers/usb/core/hcd.c:1719 dummy_timer+0x120f/0x2fa2 drivers/usb/gadget/udc/dummy_hcd.c:1965 call_timer_fn+0x179/0x650 kernel/time/timer.c:1404 expire_timers kernel/time/timer.c:1449 [inline] __run_timers kernel/time/timer.c:1773 [inline] __run_timers kernel/time/timer.c:1740 [inline] run_timer_softirq+0x5e3/0x1490 kernel/time/timer.c:1786 __do_softirq+0x221/0x912 kernel/softirq.c:292 invoke_softirq kernel/softirq.c:373 [inline] irq_exit+0x178/0x1a0 kernel/softirq.c:413 exiting_irq arch/x86/include/asm/apic.h:536 [inline] smp_apic_timer_interrupt+0x12f/0x500 arch/x86/kernel/apic/apic.c:1137 apic_timer_interrupt+0xf/0x20 arch/x86/entry/entry_64.S:830 </IRQ> RIP: 0010:default_idle+0x28/0x2e0 arch/x86/kernel/process.c:581 Code: 90 90 41 56 41 55 65 44 8b 2d 44 3a 8f 7a 41 54 55 53 0f 1f 44 00 00 e8 36 ee d0 fb e9 07 00 00 00 0f 00 2d fa dd 4f 00 fb f4 <65> 44 8b 2d 20 3a 8f 7a 0f 1f 44 00 00 5b 5d 41 5c 41 5d 41 5e c3 RSP: 0018:ffffffff86c07da8 EFLAGS: 00000246 ORIG_RAX: ffffffffffffff13 RAX: 0000000000000007 RBX: ffffffff86c2b200 RCX: 0000000000000000 RDX: 0000000000000000 RSI: 0000000000000006 RDI: ffffffff86c2ba4c RBP: fffffbfff0d85640 R08: ffffffff86c2b200 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000 R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000 cpuidle_idle_call kernel/sched/idle.c:154 [inline] do_idle+0x3b6/0x500 kernel/sched/idle.c:263 cpu_startup_entry+0x14/0x20 kernel/sched/idle.c:355 start_kernel+0x82a/0x864 init/main.c:784 secondary_startup_64+0xa4/0xb0 arch/x86/kernel/head_64.S:241 Modules linked in:
Reported-by: syzbot+f49d12d34f2321cf4df2@syzkaller.appspotmail.com Signed-off-by: Sean Young sean@mess.org Signed-off-by: Mauro Carvalho Chehab mchehab+samsung@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/media/rc/imon.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
--- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -1598,8 +1598,7 @@ static void imon_incoming_packet(struct spin_unlock_irqrestore(&ictx->kc_lock, flags);
/* send touchscreen events through input subsystem if touchpad data */ - if (ictx->display_type == IMON_DISPLAY_TYPE_VGA && len == 8 && - buf[7] == 0x86) { + if (ictx->touch && len == 8 && buf[7] == 0x86) { imon_touch_event(ictx, buf); return;
From: A Sun as1033x@comcast.net
commit e43148645d18efc3072b1ba45afaa3f385299e55 upstream.
Fix multiple cases of out of bounds (OOB) read associated with MCE device receive/input data handling.
In reference for the OOB cases below, the incoming/read (byte) data format when the MCE device responds to a command is: { cmd_prefix, subcmd, data0, data1, ... } where cmd_prefix are: MCE_CMD_PORT_SYS MCE_CMD_PORT_IR and subcmd examples are: MCE_RSP_GETPORTSTATUS MCE_RSP_EQIRNUMPORTS ... Response size dynamically depends on cmd_prefix and subcmd. So data0, data1, ... may or may not be present on input. Multiple responses may return in a single receiver buffer.
The trigger condition for OOB read is typically random or corrupt input data that fills the mceusb receiver buffer.
Case 1:
mceusb_handle_command() reads data0 (var hi) and data1 (var lo) regardless of whether the response includes such data. If { cmd_prefix, subcmd } is at the end of the receiver buffer, read past end of buffer occurs.
This case was reported by KASAN: slab-out-of-bounds Read in mceusb_dev_recv https://syzkaller.appspot.com/bug?extid=c7fdb6cb36e65f2fe8c9
Fix: In mceusb_handle_command(), change variable hi and lo to pointers, and dereference only when required.
Case 2:
If response with data is truncated at end of buffer after { cmd_prefix, subcmd }, mceusb_handle_command() reads past end of buffer for data0, data1, ...
Fix: In mceusb_process_ir_data(), check response size with remaining buffer size before invoking mceusb_handle_command(). + if (i + ir->rem < buf_len) mceusb_handle_command(ir, &ir->buf_in[i - 1]);
Case 3:
mceusb_handle_command() handles invalid/bad response such as { 0x??, MCE_RSP_GETPORTSTATUS } of length 2 as a response { MCE_CMD_PORT_SYS, MCE_RSP_GETPORTSTATUS, data0, ... } of length 7. Read OOB occurs for non-existent data0, data1, ... Cause is mceusb_handle_command() does not check cmd_prefix value.
Fix: mceusb_handle_command() must test both cmd_prefix and subcmd.
Case 4:
mceusb_process_ir_data() receiver parser state SUBCMD is possible at start (i=0) of receiver buffer resulting in buffer offset=-1 passed to mceusb_dev_printdata(). Bad offset results in OOB read before start of buffer.
[1214218.580308] mceusb 1-1.3:1.0: rx data[0]: 00 80 (length=2) [1214218.580323] mceusb 1-1.3:1.0: Unknown command 0x00 0x80 ... [1214218.580406] mceusb 1-1.3:1.0: rx data[14]: 7f 7f (length=2) [1214218.679311] mceusb 1-1.3:1.0: rx data[-1]: 80 90 (length=2) [1214218.679325] mceusb 1-1.3:1.0: End of raw IR data [1214218.679340] mceusb 1-1.3:1.0: rx data[1]: 7f 7f (length=2)
Fix: If parser_state is SUBCMD after processing receiver buffer, reset parser_state to CMD_HEADER. In effect, discard cmd_prefix at end of receiver buffer. In mceusb_dev_printdata(), abort if buffer offset is out of bounds.
Case 5:
If response with data is truncated at end of buffer after { cmd_prefix, subcmd }, mceusb_dev_printdata() reads past end of buffer for data0, data1, ... while decoding the response to print out.
Fix: In mceusb_dev_printdata(), remove unneeded buffer offset adjustments (var start and var skip) associated with MCE gen1 header. Test for truncated MCE cmd response (compare offset+len with buf_len) and skip decoding of incomplete response. Move IR data tracing to execute before the truncation test.
Signed-off-by: A Sun as1033x@comcast.net Signed-off-by: Sean Young sean@mess.org Signed-off-by: Mauro Carvalho Chehab mchehab+samsung@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/media/rc/mceusb.c | 141 +++++++++++++++++++++++++++++++--------------- 1 file changed, 98 insertions(+), 43 deletions(-)
--- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -562,7 +562,7 @@ static int mceusb_cmd_datasize(u8 cmd, u datasize = 4; break; case MCE_CMD_G_REVISION: - datasize = 2; + datasize = 4; break; case MCE_RSP_EQWAKESUPPORT: case MCE_RSP_GETWAKESOURCE: @@ -598,14 +598,9 @@ static void mceusb_dev_printdata(struct char *inout; u8 cmd, subcmd, *data; struct device *dev = ir->dev; - int start, skip = 0; u32 carrier, period;
- /* skip meaningless 0xb1 0x60 header bytes on orig receiver */ - if (ir->flags.microsoft_gen1 && !out && !offset) - skip = 2; - - if (len <= skip) + if (offset < 0 || offset >= buf_len) return;
dev_dbg(dev, "%cx data[%d]: %*ph (len=%d sz=%d)", @@ -614,11 +609,32 @@ static void mceusb_dev_printdata(struct
inout = out ? "Request" : "Got";
- start = offset + skip; - cmd = buf[start] & 0xff; - subcmd = buf[start + 1] & 0xff; - data = buf + start + 2; + cmd = buf[offset]; + subcmd = (offset + 1 < buf_len) ? buf[offset + 1] : 0; + data = &buf[offset] + 2; + + /* Trace meaningless 0xb1 0x60 header bytes on original receiver */ + if (ir->flags.microsoft_gen1 && !out && !offset) { + dev_dbg(dev, "MCE gen 1 header"); + return; + }
+ /* Trace IR data header or trailer */ + if (cmd != MCE_CMD_PORT_IR && + (cmd & MCE_PORT_MASK) == MCE_COMMAND_IRDATA) { + if (cmd == MCE_IRDATA_TRAILER) + dev_dbg(dev, "End of raw IR data"); + else + dev_dbg(dev, "Raw IR data, %d pulse/space samples", + cmd & MCE_PACKET_LENGTH_MASK); + return; + } + + /* Unexpected end of buffer? */ + if (offset + len > buf_len) + return; + + /* Decode MCE command/response */ switch (cmd) { case MCE_CMD_NULL: if (subcmd == MCE_CMD_NULL) @@ -642,7 +658,7 @@ static void mceusb_dev_printdata(struct dev_dbg(dev, "Get hw/sw rev?"); else dev_dbg(dev, "hw/sw rev %*ph", - 4, &buf[start + 2]); + 4, &buf[offset + 2]); break; case MCE_CMD_RESUME: dev_dbg(dev, "Device resume requested"); @@ -744,13 +760,6 @@ static void mceusb_dev_printdata(struct default: break; } - - if (cmd == MCE_IRDATA_TRAILER) - dev_dbg(dev, "End of raw IR data"); - else if ((cmd != MCE_CMD_PORT_IR) && - ((cmd & MCE_PORT_MASK) == MCE_COMMAND_IRDATA)) - dev_dbg(dev, "Raw IR data, %d pulse/space samples", - cmd & MCE_PACKET_LENGTH_MASK); #endif }
@@ -1127,32 +1136,62 @@ static int mceusb_set_rx_carrier_report( }
/* + * Handle PORT_SYS/IR command response received from the MCE device. + * + * Assumes single response with all its data (not truncated) + * in buf_in[]. The response itself determines its total length + * (mceusb_cmd_datasize() + 2) and hence the minimum size of buf_in[]. + * * We don't do anything but print debug spew for many of the command bits * we receive from the hardware, but some of them are useful information * we want to store so that we can use them. */ -static void mceusb_handle_command(struct mceusb_dev *ir, int index) +static void mceusb_handle_command(struct mceusb_dev *ir, u8 *buf_in) { + u8 cmd = buf_in[0]; + u8 subcmd = buf_in[1]; + u8 *hi = &buf_in[2]; /* read only when required */ + u8 *lo = &buf_in[3]; /* read only when required */ struct ir_raw_event rawir = {}; - u8 hi = ir->buf_in[index + 1] & 0xff; - u8 lo = ir->buf_in[index + 2] & 0xff; u32 carrier_cycles; u32 cycles_fix;
- switch (ir->buf_in[index]) { - /* the one and only 5-byte return value command */ - case MCE_RSP_GETPORTSTATUS: - if ((ir->buf_in[index + 4] & 0xff) == 0x00) - ir->txports_cabled |= 1 << hi; - break; + if (cmd == MCE_CMD_PORT_SYS) { + switch (subcmd) { + /* the one and only 5-byte return value command */ + case MCE_RSP_GETPORTSTATUS: + if (buf_in[5] == 0) + ir->txports_cabled |= 1 << *hi; + break;
+ /* 1-byte return value commands */ + case MCE_RSP_EQEMVER: + ir->emver = *hi; + break; + + /* No return value commands */ + case MCE_RSP_CMD_ILLEGAL: + ir->need_reset = true; + break; + + default: + break; + } + + return; + } + + if (cmd != MCE_CMD_PORT_IR) + return; + + switch (subcmd) { /* 2-byte return value commands */ case MCE_RSP_EQIRTIMEOUT: - ir->rc->timeout = US_TO_NS((hi << 8 | lo) * MCE_TIME_UNIT); + ir->rc->timeout = US_TO_NS((*hi << 8 | *lo) * MCE_TIME_UNIT); break; case MCE_RSP_EQIRNUMPORTS: - ir->num_txports = hi; - ir->num_rxports = lo; + ir->num_txports = *hi; + ir->num_rxports = *lo; break; case MCE_RSP_EQIRRXCFCNT: /* @@ -1165,7 +1204,7 @@ static void mceusb_handle_command(struct */ if (ir->carrier_report_enabled && ir->learning_active && ir->pulse_tunit > 0) { - carrier_cycles = (hi << 8 | lo); + carrier_cycles = (*hi << 8 | *lo); /* * Adjust carrier cycle count by adding * 1 missed count per pulse "on" @@ -1183,24 +1222,24 @@ static void mceusb_handle_command(struct break;
/* 1-byte return value commands */ - case MCE_RSP_EQEMVER: - ir->emver = hi; - break; case MCE_RSP_EQIRTXPORTS: - ir->tx_mask = hi; + ir->tx_mask = *hi; break; case MCE_RSP_EQIRRXPORTEN: - ir->learning_active = ((hi & 0x02) == 0x02); - if (ir->rxports_active != hi) { + ir->learning_active = ((*hi & 0x02) == 0x02); + if (ir->rxports_active != *hi) { dev_info(ir->dev, "%s-range (0x%x) receiver active", - ir->learning_active ? "short" : "long", hi); - ir->rxports_active = hi; + ir->learning_active ? "short" : "long", *hi); + ir->rxports_active = *hi; } break; + + /* No return value commands */ case MCE_RSP_CMD_ILLEGAL: case MCE_RSP_TX_TIMEOUT: ir->need_reset = true; break; + default: break; } @@ -1226,7 +1265,8 @@ static void mceusb_process_ir_data(struc ir->rem = mceusb_cmd_datasize(ir->cmd, ir->buf_in[i]); mceusb_dev_printdata(ir, ir->buf_in, buf_len, i - 1, ir->rem + 2, false); - mceusb_handle_command(ir, i); + if (i + ir->rem < buf_len) + mceusb_handle_command(ir, &ir->buf_in[i - 1]); ir->parser_state = CMD_DATA; break; case PARSE_IRDATA: @@ -1255,15 +1295,22 @@ static void mceusb_process_ir_data(struc ir->rem--; break; case CMD_HEADER: - /* decode mce packets of the form (84),AA,BB,CC,DD */ - /* IR data packets can span USB messages - rem */ ir->cmd = ir->buf_in[i]; if ((ir->cmd == MCE_CMD_PORT_IR) || ((ir->cmd & MCE_PORT_MASK) != MCE_COMMAND_IRDATA)) { + /* + * got PORT_SYS, PORT_IR, or unknown + * command response prefix + */ ir->parser_state = SUBCMD; continue; } + /* + * got IR data prefix (0x80 + num_bytes) + * decode MCE packets of the form {0x83, AA, BB, CC} + * IR data packets can span USB messages + */ ir->rem = (ir->cmd & MCE_PACKET_LENGTH_MASK); mceusb_dev_printdata(ir, ir->buf_in, buf_len, i, ir->rem + 1, false); @@ -1287,6 +1334,14 @@ static void mceusb_process_ir_data(struc if (ir->parser_state != CMD_HEADER && !ir->rem) ir->parser_state = CMD_HEADER; } + + /* + * Accept IR data spanning multiple rx buffers. + * Reject MCE command response spanning multiple rx buffers. + */ + if (ir->parser_state != PARSE_IRDATA || !ir->rem) + ir->parser_state = CMD_HEADER; + if (event) { dev_dbg(ir->dev, "processed IR data"); ir_raw_event_handle(ir->rc);
From: Alexander Potapenko glider@google.com
[ Upstream commit 0f181f9fbea8bc7ea2f7e13ae7f8c256b39e254c ]
slab_alloc_node() already zeroed out the freelist pointer if init_on_free was on. Thibaut Sautereau noticed that the same needs to be done for kmem_cache_alloc_bulk(), which performs the allocations separately.
kmem_cache_alloc_bulk() is currently used in two places in the kernel, so this change is unlikely to have a major performance impact.
SLAB doesn't require a similar change, as auto-initialization makes the allocator store the freelist pointers off-slab.
Link: http://lkml.kernel.org/r/20191007091605.30530-1-glider@google.com Fixes: 6471384af2a6 ("mm: security: introduce init_on_alloc=1 and init_on_free=1 boot options") Signed-off-by: Alexander Potapenko glider@google.com Reported-by: Thibaut Sautereau thibaut@sautereau.fr Reported-by: Kees Cook keescook@chromium.org Cc: Christoph Lameter cl@linux.com Cc: Laura Abbott labbott@redhat.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- mm/slub.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/mm/slub.c b/mm/slub.c index d2445dd1c7eda..f24ea152cdbb3 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2648,6 +2648,17 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, return p; }
+/* + * If the object has been wiped upon free, make sure it's fully initialized by + * zeroing out freelist pointer. + */ +static __always_inline void maybe_wipe_obj_freeptr(struct kmem_cache *s, + void *obj) +{ + if (unlikely(slab_want_init_on_free(s)) && obj) + memset((void *)((char *)obj + s->offset), 0, sizeof(void *)); +} + /* * Inlined fastpath so that allocation functions (kmalloc, kmem_cache_alloc) * have the fastpath folded into their functions. So no function call @@ -2736,12 +2747,8 @@ redo: prefetch_freepointer(s, next_object); stat(s, ALLOC_FASTPATH); } - /* - * If the object has been wiped upon free, make sure it's fully - * initialized by zeroing out freelist pointer. - */ - if (unlikely(slab_want_init_on_free(s)) && object) - memset(object + s->offset, 0, sizeof(void *)); + + maybe_wipe_obj_freeptr(s, object);
if (unlikely(slab_want_init_on_alloc(gfpflags, s)) && object) memset(object, 0, s->object_size); @@ -3155,10 +3162,13 @@ int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size, goto error;
c = this_cpu_ptr(s->cpu_slab); + maybe_wipe_obj_freeptr(s, p[i]); + continue; /* goto for-loop */ } c->freelist = get_freepointer(s, object); p[i] = object; + maybe_wipe_obj_freeptr(s, p[i]); } c->tid = next_tid(c->tid); local_irq_enable();
From: Oliver Neukum oneukum@suse.com
commit 1ec13abac58b6f24e32f0d3081ef4e7456e62ed8 upstream.
USBIP uses lib/scatterlist.h Hence it needs to set CONFIG_SGL_ALLOC
Signed-off-by: Oliver Neukum oneukum@suse.com Cc: stable stable@vger.kernel.org Acked-by: Shuah Khan skhan@linuxfoundation.org Link: https://lore.kernel.org/r/20191112154939.21217-1-oneukum@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/usbip/Kconfig | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/usb/usbip/Kconfig +++ b/drivers/usb/usbip/Kconfig @@ -4,6 +4,7 @@ config USBIP_CORE tristate "USB/IP support" depends on NET select USB_COMMON + select SGL_ALLOC ---help--- This enables pushing USB packets over IP to allow remote machines direct access to USB devices. It provides the
From: Hewenliang hewenliang4@huawei.com
commit 26a4d4c00f85cb844dd11dd35e848b079c2f5e8f upstream.
We should close the fd before the return of read_attr_usbip_status.
Fixes: 3391ba0e2792 ("usbip: tools: Extract generic code to be shared with vudc backend") Signed-off-by: Hewenliang hewenliang4@huawei.com Cc: stable stable@vger.kernel.org Link: https://lore.kernel.org/r/20191025043515.20053-1-hewenliang4@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- tools/usb/usbip/libsrc/usbip_host_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/tools/usb/usbip/libsrc/usbip_host_common.c +++ b/tools/usb/usbip/libsrc/usbip_host_common.c @@ -57,7 +57,7 @@ static int32_t read_attr_usbip_status(st }
value = atoi(status); - + close(fd); return value; }
From: Suwan Kim suwan.kim027@gmail.com
commit 2a9125317b247f2cf35c196f968906dcf062ae2d upstream.
Smatch reported that nents is not initialized and used in stub_recv_cmd_submit(). nents is currently initialized by sgl_alloc() and used to allocate multiple URBs when host controller doesn't support scatter-gather DMA. The use of uninitialized nents means that buf_len is zero and use_sg is true. But buffer length should not be zero when an URB uses scatter-gather DMA.
To prevent this situation, add the conditional that checks buf_len and use_sg. And move the use of nents right after the sgl_alloc() to avoid the use of uninitialized nents.
If the error occurs, it adds SDEV_EVENT_ERROR_MALLOC and stub_priv will be released by stub event handler and connection will be shut down.
Fixes: ea44d190764b ("usbip: Implement SG support to vhci-hcd and stub driver") Reported-by: kbuild test robot lkp@intel.com Reported-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: Suwan Kim suwan.kim027@gmail.com Acked-by: Shuah Khan skhan@linuxfoundation.org Cc: stable stable@vger.kernel.org Link: https://lore.kernel.org/r/20191111141035.27788-1-suwan.kim027@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/usbip/stub_rx.c | 50 ++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 18 deletions(-)
--- a/drivers/usb/usbip/stub_rx.c +++ b/drivers/usb/usbip/stub_rx.c @@ -470,18 +470,50 @@ static void stub_recv_cmd_submit(struct if (pipe == -1) return;
+ /* + * Smatch reported the error case where use_sg is true and buf_len is 0. + * In this case, It adds SDEV_EVENT_ERROR_MALLOC and stub_priv will be + * released by stub event handler and connection will be shut down. + */ priv = stub_priv_alloc(sdev, pdu); if (!priv) return;
buf_len = (unsigned long long)pdu->u.cmd_submit.transfer_buffer_length;
+ if (use_sg && !buf_len) { + dev_err(&udev->dev, "sg buffer with zero length\n"); + goto err_malloc; + } + /* allocate urb transfer buffer, if needed */ if (buf_len) { if (use_sg) { sgl = sgl_alloc(buf_len, GFP_KERNEL, &nents); if (!sgl) goto err_malloc; + + /* Check if the server's HCD supports SG */ + if (!udev->bus->sg_tablesize) { + /* + * If the server's HCD doesn't support SG, break + * a single SG request into several URBs and map + * each SG list entry to corresponding URB + * buffer. The previously allocated SG list is + * stored in priv->sgl (If the server's HCD + * support SG, SG list is stored only in + * urb->sg) and it is used as an indicator that + * the server split single SG request into + * several URBs. Later, priv->sgl is used by + * stub_complete() and stub_send_ret_submit() to + * reassemble the divied URBs. + */ + support_sg = 0; + num_urbs = nents; + priv->completed_urbs = 0; + pdu->u.cmd_submit.transfer_flags &= + ~URB_DMA_MAP_SG; + } } else { buffer = kzalloc(buf_len, GFP_KERNEL); if (!buffer) @@ -489,24 +521,6 @@ static void stub_recv_cmd_submit(struct } }
- /* Check if the server's HCD supports SG */ - if (use_sg && !udev->bus->sg_tablesize) { - /* - * If the server's HCD doesn't support SG, break a single SG - * request into several URBs and map each SG list entry to - * corresponding URB buffer. The previously allocated SG - * list is stored in priv->sgl (If the server's HCD support SG, - * SG list is stored only in urb->sg) and it is used as an - * indicator that the server split single SG request into - * several URBs. Later, priv->sgl is used by stub_complete() and - * stub_send_ret_submit() to reassemble the divied URBs. - */ - support_sg = 0; - num_urbs = nents; - priv->completed_urbs = 0; - pdu->u.cmd_submit.transfer_flags &= ~URB_DMA_MAP_SG; - } - /* allocate urb array */ priv->num_urbs = num_urbs; priv->urbs = kmalloc_array(num_urbs, sizeof(*priv->urbs), GFP_KERNEL);
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
commit 347bc8cb26388791c5881a3775cb14a3f765a674 upstream.
Add support for the Mark-10 digital force gauge device to the cp201x driver.
Based on a report and a larger patch from Joel Jennings
Reported-by: Joel Jennings joel.jennings@makeitlabs.com Cc: stable stable@vger.kernel.org Acked-by: Johan Hovold johan@kernel.org Link: https://lore.kernel.org/r/20191118092119.GA153852@kroah.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/serial/cp210x.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -125,6 +125,7 @@ static const struct usb_device_id id_tab { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ { USB_DEVICE(0x10C4, 0x8382) }, /* Cygnal Integrated Products, Inc. */ { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */ + { USB_DEVICE(0x10C4, 0x83AA) }, /* Mark-10 Digital Force Gauge */ { USB_DEVICE(0x10C4, 0x83D8) }, /* DekTec DTA Plus VHF/UHF Booster/Attenuator */ { USB_DEVICE(0x10C4, 0x8411) }, /* Kyocera GPS Module */ { USB_DEVICE(0x10C4, 0x8418) }, /* IRZ Automation Teleport SG-10 GSM/GPRS Modem */
From: Oliver Neukum oneukum@suse.com
commit 92aa5986f4f7b5a8bf282ca0f50967f4326559f5 upstream.
In case of a timeout or if a signal aborts a read communication with the device needs to be ended lest we overwrite an active URB the next time we do IO to the device, as the URB may still be active.
Signed-off-by: Oliver Neukum oneukum@suse.de Cc: stable stable@vger.kernel.org Link: https://lore.kernel.org/r/20191107142856.16774-1-oneukum@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/misc/chaoskey.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-)
--- a/drivers/usb/misc/chaoskey.c +++ b/drivers/usb/misc/chaoskey.c @@ -384,13 +384,17 @@ static int _chaoskey_fill(struct chaoske !dev->reading, (started ? NAK_TIMEOUT : ALEA_FIRST_TIMEOUT) );
- if (result < 0) + if (result < 0) { + usb_kill_urb(dev->urb); goto out; + }
- if (result == 0) + if (result == 0) { result = -ETIMEDOUT; - else + usb_kill_urb(dev->urb); + } else { result = dev->valid; + } out: /* Let the device go back to sleep eventually */ usb_autopm_put_interface(dev->interface); @@ -526,7 +530,21 @@ static int chaoskey_suspend(struct usb_i
static int chaoskey_resume(struct usb_interface *interface) { + struct chaoskey *dev; + struct usb_device *udev = interface_to_usbdev(interface); + usb_dbg(interface, "resume"); + dev = usb_get_intfdata(interface); + + /* + * We may have lost power. + * In that case the device that needs a long time + * for the first requests needs an extended timeout + * again + */ + if (le16_to_cpu(udev->descriptor.idVendor) == ALEA_VENDOR_ID) + dev->reads_started = false; + return 0; } #else
From: Oliver Neukum oneukum@suse.com
commit 91feb01596e5efc0cc922cc73f5583114dccf4d2 upstream.
The work item can operate on
1. stale memory left over from the last transfer the actual length of the data transfered needs to be checked 2. memory already freed the error handling in appledisplay_probe() needs to cancel the work in that case
Reported-and-tested-by: syzbot+495dab1f175edc9c2f13@syzkaller.appspotmail.com Signed-off-by: Oliver Neukum oneukum@suse.com Cc: stable stable@vger.kernel.org Link: https://lore.kernel.org/r/20191106124902.7765-1-oneukum@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/misc/appledisplay.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
--- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c @@ -164,7 +164,12 @@ static int appledisplay_bl_get_brightnes 0, pdata->msgdata, 2, ACD_USB_TIMEOUT); - brightness = pdata->msgdata[1]; + if (retval < 2) { + if (retval >= 0) + retval = -EMSGSIZE; + } else { + brightness = pdata->msgdata[1]; + } mutex_unlock(&pdata->sysfslock);
if (retval < 0) @@ -299,6 +304,7 @@ error: if (pdata) { if (pdata->urb) { usb_kill_urb(pdata->urb); + cancel_delayed_work_sync(&pdata->work); if (pdata->urbdata) usb_free_coherent(pdata->udev, ACD_URB_BUFFER_LEN, pdata->urbdata, pdata->urb->transfer_dma);
From: Pavel Löbl pavel@loebl.cz
commit e696d00e65e81d46e911f24b12e441037bf11b38 upstream.
Add USB ID for MOXA UPort 2210. This device contains mos7820 but it passes GPIO0 check implemented by driver and it's detected as mos7840. Hence product id check is added to force mos7820 mode.
Signed-off-by: Pavel Löbl pavel@loebl.cz Cc: stable stable@vger.kernel.org [ johan: rename id defines and add vendor-id check ] Signed-off-by: Johan Hovold johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/serial/mos7840.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
--- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -119,11 +119,15 @@ /* This driver also supports * ATEN UC2324 device using Moschip MCS7840 * ATEN UC2322 device using Moschip MCS7820 + * MOXA UPort 2210 device using Moschip MCS7820 */ #define USB_VENDOR_ID_ATENINTL 0x0557 #define ATENINTL_DEVICE_ID_UC2324 0x2011 #define ATENINTL_DEVICE_ID_UC2322 0x7820
+#define USB_VENDOR_ID_MOXA 0x110a +#define MOXA_DEVICE_ID_2210 0x2210 + /* Interrupt Routine Defines */
#define SERIAL_IIR_RLS 0x06 @@ -195,6 +199,7 @@ static const struct usb_device_id id_tab {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)}, + {USB_DEVICE(USB_VENDOR_ID_MOXA, MOXA_DEVICE_ID_2210)}, {} /* terminating entry */ }; MODULE_DEVICE_TABLE(usb, id_table); @@ -2020,6 +2025,7 @@ static int mos7840_probe(struct usb_seri const struct usb_device_id *id) { u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); + u16 vid = le16_to_cpu(serial->dev->descriptor.idVendor); u8 *buf; int device_type;
@@ -2030,6 +2036,11 @@ static int mos7840_probe(struct usb_seri goto out; }
+ if (vid == USB_VENDOR_ID_MOXA && product == MOXA_DEVICE_ID_2210) { + device_type = MOSCHIP_DEVICE_ID_7820; + goto out; + } + buf = kzalloc(VENDOR_READ_LENGTH, GFP_KERNEL); if (!buf) return -ENOMEM;
From: Johan Hovold johan@kernel.org
commit ea422312a462696093b5db59d294439796cba4ad upstream.
The driver was setting the device remote-wakeup feature during probe in violation of the USB specification (which says it should only be set just prior to suspending the device). This could potentially waste power during suspend as well as lead to spurious wakeups.
Note that USB core would clear the remote-wakeup feature at first resume.
Fixes: 0f64478cbc7a ("USB: add USB serial mos7720 driver") Cc: stable stable@vger.kernel.org # 2.6.19 Reviewed-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Johan Hovold johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/serial/mos7720.c | 4 ---- 1 file changed, 4 deletions(-)
--- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -1833,10 +1833,6 @@ static int mos7720_startup(struct usb_se product = le16_to_cpu(serial->dev->descriptor.idProduct); dev = serial->dev;
- /* setting configuration feature to one */ - usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5000); - if (product == MOSCHIP_DEVICE_ID_7715) { struct urb *urb = serial->port[0]->interrupt_in_urb;
From: Johan Hovold johan@kernel.org
commit 92fe35fb9c70a00d8fbbf5bd6172c921dd9c7815 upstream.
The driver was setting the device remote-wakeup feature during probe in violation of the USB specification (which says it should only be set just prior to suspending the device). This could potentially waste power during suspend as well as lead to spurious wakeups.
Note that USB core would clear the remote-wakeup feature at first resume.
Fixes: 3f5429746d91 ("USB: Moschip 7840 USB-Serial Driver") Cc: stable stable@vger.kernel.org # 2.6.19 Reviewed-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Johan Hovold johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/serial/mos7840.c | 5 ----- 1 file changed, 5 deletions(-)
--- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -2290,11 +2290,6 @@ out: goto error; } else dev_dbg(&port->dev, "ZLP_REG5 Writing success status%d\n", status); - - /* setting configuration feature to one */ - usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - 0x03, 0x00, 0x01, 0x00, NULL, 0x00, - MOS_WDR_TIMEOUT); } return 0; error:
From: Aleksander Morgado aleksander@aleksander.es
commit 957c31ea082e3fe5196f46d5b04018b10de47400 upstream.
The device exposes AT, NMEA and DIAG ports in both USB configurations. Exactly same layout as the default DW5821e module, just a different vid/pid.
P: Vendor=413c ProdID=81e0 Rev=03.18 S: Manufacturer=Dell Inc. S: Product=DW5821e-eSIM Snapdragon X20 LTE S: SerialNumber=0123456789ABCDEF C: #Ifs= 6 Cfg#= 1 Atr=a0 MxPwr=500mA I: If#=0x0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan I: If#=0x1 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=00 Prot=00 Driver=usbhid I: If#=0x2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option I: If#=0x3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option I: If#=0x4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option I: If#=0x5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option
P: Vendor=413c ProdID=81e0 Rev=03.18 S: Manufacturer=Dell Inc. S: Product=DW5821e-eSIM Snapdragon X20 LTE S: SerialNumber=0123456789ABCDEF C: #Ifs= 7 Cfg#= 2 Atr=a0 MxPwr=500mA I: If#=0x0 Alt= 0 #EPs= 1 Cls=02(commc) Sub=0e Prot=00 Driver=cdc_mbim I: If#=0x1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim I: If#=0x2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option I: If#=0x3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option I: If#=0x4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option I: If#=0x5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option I: If#=0x6 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
Signed-off-by: Aleksander Morgado aleksander@aleksander.es Cc: stable stable@vger.kernel.org Signed-off-by: Johan Hovold johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/serial/option.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -197,6 +197,7 @@ static void option_instat_callback(struc #define DELL_PRODUCT_5804_MINICARD_ATT 0x819b /* Novatel E371 */
#define DELL_PRODUCT_5821E 0x81d7 +#define DELL_PRODUCT_5821E_ESIM 0x81e0
#define KYOCERA_VENDOR_ID 0x0c88 #define KYOCERA_PRODUCT_KPC650 0x17da @@ -1044,6 +1045,8 @@ static const struct usb_device_id option { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5804_MINICARD_ATT, 0xff, 0xff, 0xff) }, { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5821E), .driver_info = RSVD(0) | RSVD(1) | RSVD(6) }, + { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5821E_ESIM), + .driver_info = RSVD(0) | RSVD(1) | RSVD(6) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, /* ADU-E100, ADU-310 */ { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) },
From: Aleksander Morgado aleksander@aleksander.es
commit f0797095423e6ea3b4be61134ee353c7f504d440 upstream.
These are the Foxconn-branded variants of the Dell DW5821e modules, same USB layout as those. The device exposes AT, NMEA and DIAG ports in both USB configurations.
P: Vendor=0489 ProdID=e0b4 Rev=03.18 S: Manufacturer=FII S: Product=T77W968 LTE S: SerialNumber=0123456789ABCDEF C: #Ifs= 6 Cfg#= 1 Atr=a0 MxPwr=500mA I: If#=0x0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan I: If#=0x1 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=00 Prot=00 Driver=usbhid I: If#=0x2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option I: If#=0x3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option I: If#=0x4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option I: If#=0x5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option
P: Vendor=0489 ProdID=e0b4 Rev=03.18 S: Manufacturer=FII S: Product=T77W968 LTE S: SerialNumber=0123456789ABCDEF C: #Ifs= 7 Cfg#= 2 Atr=a0 MxPwr=500mA I: If#=0x0 Alt= 0 #EPs= 1 Cls=02(commc) Sub=0e Prot=00 Driver=cdc_mbim I: If#=0x1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim I: If#=0x2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option I: If#=0x3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option I: If#=0x4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option I: If#=0x5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option I: If#=0x6 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
Signed-off-by: Aleksander Morgado aleksander@aleksander.es [ johan: drop id defines ] Cc: stable stable@vger.kernel.org Signed-off-by: Johan Hovold johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/serial/option.c | 4 ++++ 1 file changed, 4 insertions(+)
--- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1993,6 +1993,10 @@ static const struct usb_device_id option { USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0xa31d, 0xff, 0x06, 0x13) }, { USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0xa31d, 0xff, 0x06, 0x14) }, { USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0xa31d, 0xff, 0x06, 0x1b) }, + { USB_DEVICE(0x0489, 0xe0b4), /* Foxconn T77W968 */ + .driver_info = RSVD(0) | RSVD(1) | RSVD(6) }, + { USB_DEVICE(0x0489, 0xe0b5), /* Foxconn T77W968 ESIM */ + .driver_info = RSVD(0) | RSVD(1) | RSVD(6) }, { USB_DEVICE(0x1508, 0x1001), /* Fibocom NL668 */ .driver_info = RSVD(4) | RSVD(5) | RSVD(6) }, { USB_DEVICE(0x2cb7, 0x0104), /* Fibocom NL678 series */
From: Bernd Porr mail@berndporr.me.uk
commit 5618332e5b955b4bff06d0b88146b971c8dd7b32 upstream.
The userspace comedilib function 'get_cmd_generic_timed' fills the cmd structure with an informed guess and then calls the function 'usbduxfast_ai_cmdtest' in this driver repeatedly while 'usbduxfast_ai_cmdtest' is modifying the cmd struct until it no longer changes. However, because of rounding errors this never converged because 'steps = (cmd->convert_arg * 30) / 1000' and then back to 'cmd->convert_arg = (steps * 1000) / 30' won't be the same because of rounding errors. 'Steps' should only be converted back to the 'convert_arg' if 'steps' has actually been modified. In addition the case of steps being 0 wasn't checked which is also now done.
Signed-off-by: Bernd Porr mail@berndporr.me.uk Cc: stable@vger.kernel.org # 4.4+ Reviewed-by: Ian Abbott abbotti@mev.co.uk Link: https://lore.kernel.org/r/20191118230759.1727-1-mail@berndporr.me.uk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/staging/comedi/drivers/usbduxfast.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-)
--- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright (C) 2004-2014 Bernd Porr, mail@berndporr.me.uk + * Copyright (C) 2004-2019 Bernd Porr, mail@berndporr.me.uk */
/* @@ -8,7 +8,7 @@ * Description: University of Stirling USB DAQ & INCITE Technology Limited * Devices: [ITL] USB-DUX-FAST (usbduxfast) * Author: Bernd Porr mail@berndporr.me.uk - * Updated: 10 Oct 2014 + * Updated: 16 Nov 2019 * Status: stable */
@@ -22,6 +22,7 @@ * * * Revision history: + * 1.0: Fixed a rounding error in usbduxfast_ai_cmdtest * 0.9: Dropping the first data packet which seems to be from the last transfer. * Buffer overflows in the FX2 are handed over to comedi. * 0.92: Dropping now 4 packets. The quad buffer has to be emptied. @@ -350,6 +351,7 @@ static int usbduxfast_ai_cmdtest(struct struct comedi_cmd *cmd) { int err = 0; + int err2 = 0; unsigned int steps; unsigned int arg;
@@ -399,11 +401,16 @@ static int usbduxfast_ai_cmdtest(struct */ steps = (cmd->convert_arg * 30) / 1000; if (cmd->chanlist_len != 1) - err |= comedi_check_trigger_arg_min(&steps, - MIN_SAMPLING_PERIOD); - err |= comedi_check_trigger_arg_max(&steps, MAX_SAMPLING_PERIOD); - arg = (steps * 1000) / 30; - err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg); + err2 |= comedi_check_trigger_arg_min(&steps, + MIN_SAMPLING_PERIOD); + else + err2 |= comedi_check_trigger_arg_min(&steps, 1); + err2 |= comedi_check_trigger_arg_max(&steps, MAX_SAMPLING_PERIOD); + if (err2) { + err |= err2; + arg = (steps * 1000) / 30; + err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg); + }
if (cmd->stop_src == TRIG_COUNT) err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
From: "Christopher M. Riedl" cmr@informatik.wtf
commit d8f0e0b073e1ec52a05f0c2a56318b47387d2f10 upstream.
Add support for disabling the kernel implemented spectre v2 mitigation (count cache flush on context switch) via the nospectre_v2 and mitigations=off cmdline options.
Suggested-by: Michael Ellerman mpe@ellerman.id.au Signed-off-by: Christopher M. Riedl cmr@informatik.wtf Reviewed-by: Andrew Donnellan ajd@linux.ibm.com Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20190524024647.381-1-cmr@informatik.wtf Signed-off-by: Daniel Axtens dja@axtens.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/powerpc/kernel/security.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-)
--- a/arch/powerpc/kernel/security.c +++ b/arch/powerpc/kernel/security.c @@ -28,7 +28,7 @@ static enum count_cache_flush_type count bool barrier_nospec_enabled; static bool no_nospec; static bool btb_flush_enabled; -#ifdef CONFIG_PPC_FSL_BOOK3E +#if defined(CONFIG_PPC_FSL_BOOK3E) || defined(CONFIG_PPC_BOOK3S_64) static bool no_spectrev2; #endif
@@ -114,7 +114,7 @@ static __init int security_feature_debug device_initcall(security_feature_debugfs_init); #endif /* CONFIG_DEBUG_FS */
-#ifdef CONFIG_PPC_FSL_BOOK3E +#if defined(CONFIG_PPC_FSL_BOOK3E) || defined(CONFIG_PPC_BOOK3S_64) static int __init handle_nospectre_v2(char *p) { no_spectrev2 = true; @@ -122,6 +122,9 @@ static int __init handle_nospectre_v2(ch return 0; } early_param("nospectre_v2", handle_nospectre_v2); +#endif /* CONFIG_PPC_FSL_BOOK3E || CONFIG_PPC_BOOK3S_64 */ + +#ifdef CONFIG_PPC_FSL_BOOK3E void setup_spectre_v2(void) { if (no_spectrev2 || cpu_mitigations_off()) @@ -399,7 +402,17 @@ static void toggle_count_cache_flush(boo
void setup_count_cache_flush(void) { - toggle_count_cache_flush(true); + bool enable = true; + + if (no_spectrev2 || cpu_mitigations_off()) { + if (security_ftr_enabled(SEC_FTR_BCCTRL_SERIALISED) || + security_ftr_enabled(SEC_FTR_COUNT_CACHE_DISABLED)) + pr_warn("Spectre v2 mitigations not under software control, can't disable\n"); + + enable = false; + } + + toggle_count_cache_flush(enable); }
#ifdef CONFIG_DEBUG_FS
From: Michael Ellerman mpe@ellerman.id.au
commit 39e72bf96f5847ba87cc5bd7a3ce0fed813dc9ad upstream.
In commit ee13cb249fab ("powerpc/64s: Add support for software count cache flush"), I added support for software to flush the count cache (indirect branch cache) on context switch if firmware told us that was the required mitigation for Spectre v2.
As part of that code we also added a software flush of the link stack (return address stack), which protects against Spectre-RSB between user processes.
That is all correct for CPUs that activate that mitigation, which is currently Power9 Nimbus DD2.3.
What I got wrong is that on older CPUs, where firmware has disabled the count cache, we also need to flush the link stack on context switch.
To fix it we create a new feature bit which is not set by firmware, which tells us we need to flush the link stack. We set that when firmware tells us that either of the existing Spectre v2 mitigations are enabled.
Then we adjust the patching code so that if we see that feature bit we enable the link stack flush. If we're also told to flush the count cache in software then we fall through and do that also.
On the older CPUs we don't need to do do the software count cache flush, firmware has disabled it, so in that case we patch in an early return after the link stack flush.
The naming of some of the functions is awkward after this patch, because they're called "count cache" but they also do link stack. But we'll fix that up in a later commit to ease backporting.
This is the fix for CVE-2019-18660.
Reported-by: Anthony Steinhauser asteinhauser@google.com Fixes: ee13cb249fab ("powerpc/64s: Add support for software count cache flush") Cc: stable@vger.kernel.org # v4.4+ Signed-off-by: Michael Ellerman mpe@ellerman.id.au Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/powerpc/include/asm/asm-prototypes.h | 1 arch/powerpc/include/asm/security_features.h | 3 + arch/powerpc/kernel/entry_64.S | 6 +++ arch/powerpc/kernel/security.c | 48 ++++++++++++++++++++++++--- 4 files changed, 54 insertions(+), 4 deletions(-)
--- a/arch/powerpc/include/asm/asm-prototypes.h +++ b/arch/powerpc/include/asm/asm-prototypes.h @@ -140,6 +140,7 @@ void _kvmppc_save_tm_pr(struct kvm_vcpu /* Patch sites */ extern s32 patch__call_flush_count_cache; extern s32 patch__flush_count_cache_return; +extern s32 patch__flush_link_stack_return; extern s32 patch__memset_nocache, patch__memcpy_nocache;
extern long flush_count_cache; --- a/arch/powerpc/include/asm/security_features.h +++ b/arch/powerpc/include/asm/security_features.h @@ -81,6 +81,9 @@ static inline bool security_ftr_enabled( // Software required to flush count cache on context switch #define SEC_FTR_FLUSH_COUNT_CACHE 0x0000000000000400ull
+// Software required to flush link stack on context switch +#define SEC_FTR_FLUSH_LINK_STACK 0x0000000000001000ull +
// Features enabled by default #define SEC_FTR_DEFAULT \ --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -546,6 +546,7 @@ flush_count_cache: /* Save LR into r9 */ mflr r9
+ // Flush the link stack .rept 64 bl .+4 .endr @@ -555,6 +556,11 @@ flush_count_cache: .balign 32 /* Restore LR */ 1: mtlr r9 + + // If we're just flushing the link stack, return here +3: nop + patch_site 3b patch__flush_link_stack_return + li r9,0x7fff mtctr r9
--- a/arch/powerpc/kernel/security.c +++ b/arch/powerpc/kernel/security.c @@ -24,6 +24,7 @@ enum count_cache_flush_type { COUNT_CACHE_FLUSH_HW = 0x4, }; static enum count_cache_flush_type count_cache_flush_type = COUNT_CACHE_FLUSH_NONE; +static bool link_stack_flush_enabled;
bool barrier_nospec_enabled; static bool no_nospec; @@ -212,11 +213,19 @@ ssize_t cpu_show_spectre_v2(struct devic
if (ccd) seq_buf_printf(&s, "Indirect branch cache disabled"); + + if (link_stack_flush_enabled) + seq_buf_printf(&s, ", Software link stack flush"); + } else if (count_cache_flush_type != COUNT_CACHE_FLUSH_NONE) { seq_buf_printf(&s, "Mitigation: Software count cache flush");
if (count_cache_flush_type == COUNT_CACHE_FLUSH_HW) seq_buf_printf(&s, " (hardware accelerated)"); + + if (link_stack_flush_enabled) + seq_buf_printf(&s, ", Software link stack flush"); + } else if (btb_flush_enabled) { seq_buf_printf(&s, "Mitigation: Branch predictor state flush"); } else { @@ -377,18 +386,40 @@ static __init int stf_barrier_debugfs_in device_initcall(stf_barrier_debugfs_init); #endif /* CONFIG_DEBUG_FS */
+static void no_count_cache_flush(void) +{ + count_cache_flush_type = COUNT_CACHE_FLUSH_NONE; + pr_info("count-cache-flush: software flush disabled.\n"); +} + static void toggle_count_cache_flush(bool enable) { - if (!enable || !security_ftr_enabled(SEC_FTR_FLUSH_COUNT_CACHE)) { + if (!security_ftr_enabled(SEC_FTR_FLUSH_COUNT_CACHE) && + !security_ftr_enabled(SEC_FTR_FLUSH_LINK_STACK)) + enable = false; + + if (!enable) { patch_instruction_site(&patch__call_flush_count_cache, PPC_INST_NOP); - count_cache_flush_type = COUNT_CACHE_FLUSH_NONE; - pr_info("count-cache-flush: software flush disabled.\n"); + pr_info("link-stack-flush: software flush disabled.\n"); + link_stack_flush_enabled = false; + no_count_cache_flush(); return; }
+ // This enables the branch from _switch to flush_count_cache patch_branch_site(&patch__call_flush_count_cache, (u64)&flush_count_cache, BRANCH_SET_LINK);
+ pr_info("link-stack-flush: software flush enabled.\n"); + link_stack_flush_enabled = true; + + // If we just need to flush the link stack, patch an early return + if (!security_ftr_enabled(SEC_FTR_FLUSH_COUNT_CACHE)) { + patch_instruction_site(&patch__flush_link_stack_return, PPC_INST_BLR); + no_count_cache_flush(); + return; + } + if (!security_ftr_enabled(SEC_FTR_BCCTR_FLUSH_ASSIST)) { count_cache_flush_type = COUNT_CACHE_FLUSH_SW; pr_info("count-cache-flush: full software flush sequence enabled.\n"); @@ -407,11 +438,20 @@ void setup_count_cache_flush(void) if (no_spectrev2 || cpu_mitigations_off()) { if (security_ftr_enabled(SEC_FTR_BCCTRL_SERIALISED) || security_ftr_enabled(SEC_FTR_COUNT_CACHE_DISABLED)) - pr_warn("Spectre v2 mitigations not under software control, can't disable\n"); + pr_warn("Spectre v2 mitigations not fully under software control, can't disable\n");
enable = false; }
+ /* + * There's no firmware feature flag/hypervisor bit to tell us we need to + * flush the link stack on context switch. So we set it here if we see + * either of the Spectre v2 mitigations that aim to protect userspace. + */ + if (security_ftr_enabled(SEC_FTR_COUNT_CACHE_DISABLED) || + security_ftr_enabled(SEC_FTR_FLUSH_COUNT_CACHE)) + security_ftr_set(SEC_FTR_FLUSH_LINK_STACK); + toggle_count_cache_flush(enable); }
From: Michael Ellerman mpe@ellerman.id.au
commit af2e8c68b9c5403f77096969c516f742f5bb29e0 upstream.
On some systems that are vulnerable to Spectre v2, it is up to software to flush the link stack (return address stack), in order to protect against Spectre-RSB.
When exiting from a guest we do some house keeping and then potentially exit to C code which is several stack frames deep in the host kernel. We will then execute a series of returns without preceeding calls, opening up the possiblity that the guest could have poisoned the link stack, and direct speculative execution of the host to a gadget of some sort.
To prevent this we add a flush of the link stack on exit from a guest.
Signed-off-by: Michael Ellerman mpe@ellerman.id.au Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/powerpc/include/asm/asm-prototypes.h | 2 ++ arch/powerpc/kernel/security.c | 9 +++++++++ arch/powerpc/kvm/book3s_hv_rmhandlers.S | 30 ++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+)
--- a/arch/powerpc/include/asm/asm-prototypes.h +++ b/arch/powerpc/include/asm/asm-prototypes.h @@ -141,9 +141,11 @@ void _kvmppc_save_tm_pr(struct kvm_vcpu extern s32 patch__call_flush_count_cache; extern s32 patch__flush_count_cache_return; extern s32 patch__flush_link_stack_return; +extern s32 patch__call_kvm_flush_link_stack; extern s32 patch__memset_nocache, patch__memcpy_nocache;
extern long flush_count_cache; +extern long kvm_flush_link_stack;
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM void kvmppc_save_tm_hv(struct kvm_vcpu *vcpu, u64 msr, bool preserve_nv); --- a/arch/powerpc/kernel/security.c +++ b/arch/powerpc/kernel/security.c @@ -400,6 +400,9 @@ static void toggle_count_cache_flush(boo
if (!enable) { patch_instruction_site(&patch__call_flush_count_cache, PPC_INST_NOP); +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE + patch_instruction_site(&patch__call_kvm_flush_link_stack, PPC_INST_NOP); +#endif pr_info("link-stack-flush: software flush disabled.\n"); link_stack_flush_enabled = false; no_count_cache_flush(); @@ -410,6 +413,12 @@ static void toggle_count_cache_flush(boo patch_branch_site(&patch__call_flush_count_cache, (u64)&flush_count_cache, BRANCH_SET_LINK);
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE + // This enables the branch from guest_exit_cont to kvm_flush_link_stack + patch_branch_site(&patch__call_kvm_flush_link_stack, + (u64)&kvm_flush_link_stack, BRANCH_SET_LINK); +#endif + pr_info("link-stack-flush: software flush enabled.\n"); link_stack_flush_enabled = true;
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S @@ -11,6 +11,7 @@ */
#include <asm/ppc_asm.h> +#include <asm/code-patching-asm.h> #include <asm/kvm_asm.h> #include <asm/reg.h> #include <asm/mmu.h> @@ -1458,6 +1459,13 @@ guest_exit_cont: /* r9 = vcpu, r12 = tr 1: #endif /* CONFIG_KVM_XICS */
+ /* + * Possibly flush the link stack here, before we do a blr in + * guest_exit_short_path. + */ +1: nop + patch_site 1b patch__call_kvm_flush_link_stack + /* If we came in through the P9 short path, go back out to C now */ lwz r0, STACK_SLOT_SHORT_PATH(r1) cmpwi r0, 0 @@ -1933,6 +1941,28 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300) mtlr r0 blr
+.balign 32 +.global kvm_flush_link_stack +kvm_flush_link_stack: + /* Save LR into r0 */ + mflr r0 + + /* Flush the link stack. On Power8 it's up to 32 entries in size. */ + .rept 32 + bl .+4 + .endr + + /* And on Power9 it's up to 64. */ +BEGIN_FTR_SECTION + .rept 32 + bl .+4 + .endr +END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300) + + /* Restore LR */ + mtlr r0 + blr + kvmppc_guest_external: /* External interrupt, first check for host_ipi. If this is * set, we know the host wants us out so let's do it now
On 27/11/2019 20:31, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.3.14 release. There are 95 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 Fri, 29 Nov 2019 20:18:09 +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/v5.x/stable-review/patch-5.3.14-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.3.y and the diffstat can be found below.
thanks,
greg k-h
...
Jouni Hogander jouni.hogander@unikie.com net-sysfs: Fix reference count leak in rx|netdev_queue_add_kobject
The above commit is causing a boot regression (NULL pointer deference crash) on Tegra210 for v5.3. Reverting this on top of 5.3.14-rc1 fixes the problem. Complete results for Tegra are here ...
Test results for stable-v5.3: 13 builds: 13 pass, 0 fail 24 boots: 18 pass, 6 fail 34 tests: 34 pass, 0 fail
Linux version: 5.3.14-rc1-g7173a2d18fa6 Boards tested: tegra124-jetson-tk1, tegra186-p2771-0000, tegra194-p2972-0000, tegra20-ventana, tegra210-p2371-2180, tegra30-cardhu-a04
Cheers Jon
On Thu, Nov 28, 2019 at 09:15:45AM +0000, Jon Hunter wrote:
On 27/11/2019 20:31, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.3.14 release. There are 95 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 Fri, 29 Nov 2019 20:18:09 +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/v5.x/stable-review/patch-5.3.14-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.3.y and the diffstat can be found below.
thanks,
greg k-h
...
Jouni Hogander jouni.hogander@unikie.com net-sysfs: Fix reference count leak in rx|netdev_queue_add_kobject
The above commit is causing a boot regression (NULL pointer deference crash) on Tegra210 for v5.3. Reverting this on top of 5.3.14-rc1 fixes the problem. Complete results for Tegra are here ...
Test results for stable-v5.3: 13 builds: 13 pass, 0 fail 24 boots: 18 pass, 6 fail 34 tests: 34 pass, 0 fail
Linux version: 5.3.14-rc1-g7173a2d18fa6 Boards tested: tegra124-jetson-tk1, tegra186-p2771-0000, tegra194-p2972-0000, tegra20-ventana, tegra210-p2371-2180, tegra30-cardhu-a04
I've pushed out a -rc2 that should resolve this now. If not, please let me know.
thansk,
greg k-h
On 28/11/2019 10:36, Greg Kroah-Hartman wrote:
On Thu, Nov 28, 2019 at 09:15:45AM +0000, Jon Hunter wrote:
On 27/11/2019 20:31, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.3.14 release. There are 95 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 Fri, 29 Nov 2019 20:18:09 +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/v5.x/stable-review/patch-5.3.14-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.3.y and the diffstat can be found below.
thanks,
greg k-h
...
Jouni Hogander jouni.hogander@unikie.com net-sysfs: Fix reference count leak in rx|netdev_queue_add_kobject
The above commit is causing a boot regression (NULL pointer deference crash) on Tegra210 for v5.3. Reverting this on top of 5.3.14-rc1 fixes the problem. Complete results for Tegra are here ...
Test results for stable-v5.3: 13 builds: 13 pass, 0 fail 24 boots: 18 pass, 6 fail 34 tests: 34 pass, 0 fail
Linux version: 5.3.14-rc1-g7173a2d18fa6 Boards tested: tegra124-jetson-tk1, tegra186-p2771-0000, tegra194-p2972-0000, tegra20-ventana, tegra210-p2371-2180, tegra30-cardhu-a04
I've pushed out a -rc2 that should resolve this now. If not, please let me know.
Yes all passing now thanks!
Test results for stable-v5.3: 13 builds: 13 pass, 0 fail 22 boots: 22 pass, 0 fail 38 tests: 38 pass, 0 fail
Linux version: 5.3.14-rc2-g27442d398302 Boards tested: tegra124-jetson-tk1, tegra186-p2771-0000, tegra194-p2972-0000, tegra20-ventana, tegra210-p2371-2180, tegra30-cardhu-a04
Cheers Jon
On 11/27/19 1:31 PM, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.3.14 release. There are 95 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 Fri, 29 Nov 2019 20:18:09 +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/v5.x/stable-review/patch-5.3.14-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.3.y and the diffstat can be found below.
thanks,
greg k-h
It didn't boot. Panics in netns_cleanup_net()?
I am attaching a screenshot for the panic. I will try rc2 and see if it improves things.
thanks, -- Shuah
On Thu, Nov 28, 2019 at 08:47:51AM -0700, shuah wrote:
On 11/27/19 1:31 PM, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.3.14 release. There are 95 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 Fri, 29 Nov 2019 20:18:09 +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/v5.x/stable-review/patch-5.3.14-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.3.y and the diffstat can be found below.
thanks,
greg k-h
It didn't boot. Panics in netns_cleanup_net()?
I am attaching a screenshot for the panic. I will try rc2 and see if it improves things.
-rc2 should fix this, if not, please let me know.
I also did -rc2 for 4.19 and 4.14 with this fix.
thanks,
greg k-h
On 11/28/19 8:59 AM, Greg Kroah-Hartman wrote:
On Thu, Nov 28, 2019 at 08:47:51AM -0700, shuah wrote:
On 11/27/19 1:31 PM, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.3.14 release. There are 95 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 Fri, 29 Nov 2019 20:18:09 +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/v5.x/stable-review/patch-5.3.14-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.3.y and the diffstat can be found below.
thanks,
greg k-h
It didn't boot. Panics in netns_cleanup_net()?
I am attaching a screenshot for the panic. I will try rc2 and see if it improves things.
-rc2 should fix this, if not, please let me know.
I also did -rc2 for 4.19 and 4.14 with this fix.
rc2 worked for me.
thanks, -- Shuah
On 11/27/19 12:31 PM, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.3.14 release. There are 95 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 Fri, 29 Nov 2019 20:18:09 +0000. Anything received after that time might be too late.
Build results: total: 158 pass: 158 fail: 0 Qemu test results: total: 391 pass: 391 fail: 0
Guenter
Hello!
On 11/27/19 2:31 PM, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.3.14 release. There are 95 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 Fri, 29 Nov 2019 20:18:09 +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/v5.x/stable-review/patch-5.3.14-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.3.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: 5.3.14-rc2 git repo: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git git branch: linux-5.3.y git commit: 27442d39830209266d439effe7503146b8f4d0a6 git describe: v5.3.13-97-g27442d398302 Test details: https://qa-reports.linaro.org/lkft/linux-stable-rc-5.3-oe/build/v5.3.13-97-g...
No regressions (compared to build v5.3.13)
No fixes (compared to build v5.3.13)
Ran 24992 total tests in the following environments and test suites.
Environments -------------- - dragonboard-410c - hi6220-hikey - i386 - juno-r2 - qemu_arm - qemu_arm64 - qemu_i386 - qemu_x86_64 - x15 - x86
Test Suites ----------- * build * install-android-platform-tools-r2600 * kselftest * libgpiod * libhugetlbfs * linux-log-parser * ltp-containers-tests * ltp-dio-tests * ltp-fs-tests * ltp-hugetlb-tests * ltp-io-tests * ltp-ipc-tests * ltp-mm-tests * ltp-cap_bounds-tests * ltp-commands-tests * ltp-cpuhotplug-tests * ltp-cve-tests * ltp-fcntl-locktests-tests * ltp-filecaps-tests * ltp-fs_bind-tests * ltp-fs_perms_simple-tests * ltp-fsx-tests * ltp-math-tests * ltp-nptl-tests * ltp-pty-tests * ltp-sched-tests * ltp-securebits-tests * ltp-syscalls-tests * network-basic-tests * perf * spectre-meltdown-checker-test * v4l2-compliance * ltp-open-posix-tests * kvm-unit-tests * kselftest-vsyscall-mode-native * kselftest-vsyscall-mode-none * ssuite
Greetings!
Daniel Díaz daniel.diaz@linaro.org
linux-stable-mirror@lists.linaro.org