usb_udc_connect_control does not check to see if the udc has already
been started. This causes gadget->ops->pullup to be called through
usb_gadget_connect when invoked from usb_udc_vbus_handler even before
usb_gadget_udc_start is called. Guard this by checking for udc->started
in usb_udc_connect_control before invoking usb_gadget_connect.
Guarding udc->vbus, udc->started, gadget->connect, gadget->deactivate
related functions with connect_lock. usb_gadget_connect_locked,
usb_gadget_disconnect_locked, usb_udc_connect_control_locked,
usb_gadget_udc_start_locked, usb_gadget_udc_stop_locked are called with
this lock held as they can be simulataneously invoked from different code
paths.
Adding an additional check to make sure udc is started(udc->started)
before pullup callback is invoked.
Cc: stable(a)vger.kernel.org
Fixes: 628ef0d273a6 ("usb: udc: add usb_udc_vbus_handler")
Signed-off-by: Badhri Jagan Sridharan <badhri(a)google.com>
---
Changes since v3:
* Make internal gadget_connect/disconnect functions static
Changes since v2:
* Added __must_hold marking for connect_lock
Changes since v1:
* Fixed commit message comments.
* Renamed udc_connect_control_lock to connect_lock and made it per
device.
* udc->vbus, udc->started, gadget->connect, gadget->deactivate are all
now guarded by connect_lock.
* Code now checks for udc->started to be set before invoking pullup
callback.
---
drivers/usb/gadget/udc/core.c | 148 ++++++++++++++++++++++++----------
1 file changed, 104 insertions(+), 44 deletions(-)
diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
index 3dcbba739db6..af92c2e8e10c 100644
--- a/drivers/usb/gadget/udc/core.c
+++ b/drivers/usb/gadget/udc/core.c
@@ -37,6 +37,10 @@ static struct bus_type gadget_bus_type;
* @vbus: for udcs who care about vbus status, this value is real vbus status;
* for udcs who do not care about vbus status, this value is always true
* @started: the UDC's started state. True if the UDC had started.
+ * @connect_lock: protects udc->vbus, udc->started, gadget->connect, gadget->deactivate related
+ * functions. usb_gadget_connect_locked, usb_gadget_disconnect_locked,
+ * usb_udc_connect_control_locked, usb_gadget_udc_start_locked, usb_gadget_udc_stop_locked are
+ * called with this lock held.
*
* This represents the internal data structure which is used by the UDC-class
* to hold information about udc driver and gadget together.
@@ -48,6 +52,7 @@ struct usb_udc {
struct list_head list;
bool vbus;
bool started;
+ struct mutex connect_lock;
};
static struct class *udc_class;
@@ -687,17 +692,9 @@ int usb_gadget_vbus_disconnect(struct usb_gadget *gadget)
}
EXPORT_SYMBOL_GPL(usb_gadget_vbus_disconnect);
-/**
- * usb_gadget_connect - software-controlled connect to USB host
- * @gadget:the peripheral being connected
- *
- * Enables the D+ (or potentially D-) pullup. The host will start
- * enumerating this gadget when the pullup is active and a VBUS session
- * is active (the link is powered).
- *
- * Returns zero on success, else negative errno.
- */
-int usb_gadget_connect(struct usb_gadget *gadget)
+/* Internal version of usb_gadget_connect needs to be called with connect_lock held. */
+static int usb_gadget_connect_locked(struct usb_gadget *gadget)
+ __must_hold(&gadget->udc->connect_lock)
{
int ret = 0;
@@ -706,10 +703,12 @@ int usb_gadget_connect(struct usb_gadget *gadget)
goto out;
}
- if (gadget->deactivated) {
+ if (gadget->deactivated || !gadget->udc->started) {
/*
* If gadget is deactivated we only save new state.
* Gadget will be connected automatically after activation.
+ *
+ * udc first needs to be started before gadget can be pulled up.
*/
gadget->connected = true;
goto out;
@@ -724,22 +723,32 @@ int usb_gadget_connect(struct usb_gadget *gadget)
return ret;
}
-EXPORT_SYMBOL_GPL(usb_gadget_connect);
/**
- * usb_gadget_disconnect - software-controlled disconnect from USB host
- * @gadget:the peripheral being disconnected
- *
- * Disables the D+ (or potentially D-) pullup, which the host may see
- * as a disconnect (when a VBUS session is active). Not all systems
- * support software pullup controls.
+ * usb_gadget_connect - software-controlled connect to USB host
+ * @gadget:the peripheral being connected
*
- * Following a successful disconnect, invoke the ->disconnect() callback
- * for the current gadget driver so that UDC drivers don't need to.
+ * Enables the D+ (or potentially D-) pullup. The host will start
+ * enumerating this gadget when the pullup is active and a VBUS session
+ * is active (the link is powered).
*
* Returns zero on success, else negative errno.
*/
-int usb_gadget_disconnect(struct usb_gadget *gadget)
+int usb_gadget_connect(struct usb_gadget *gadget)
+{
+ int ret;
+
+ mutex_lock(&gadget->udc->connect_lock);
+ ret = usb_gadget_connect_locked(gadget);
+ mutex_unlock(&gadget->udc->connect_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_connect);
+
+/* Internal version of usb_gadget_disconnect needs to be called with connect_lock held. */
+static int usb_gadget_disconnect_locked(struct usb_gadget *gadget)
+ __must_hold(&gadget->udc->connect_lock)
{
int ret = 0;
@@ -751,10 +760,12 @@ int usb_gadget_disconnect(struct usb_gadget *gadget)
if (!gadget->connected)
goto out;
- if (gadget->deactivated) {
+ if (gadget->deactivated || !gadget->udc->started) {
/*
* If gadget is deactivated we only save new state.
* Gadget will stay disconnected after activation.
+ *
+ * udc should have been started before gadget being pulled down.
*/
gadget->connected = false;
goto out;
@@ -774,6 +785,30 @@ int usb_gadget_disconnect(struct usb_gadget *gadget)
return ret;
}
+
+/**
+ * usb_gadget_disconnect - software-controlled disconnect from USB host
+ * @gadget:the peripheral being disconnected
+ *
+ * Disables the D+ (or potentially D-) pullup, which the host may see
+ * as a disconnect (when a VBUS session is active). Not all systems
+ * support software pullup controls.
+ *
+ * Following a successful disconnect, invoke the ->disconnect() callback
+ * for the current gadget driver so that UDC drivers don't need to.
+ *
+ * Returns zero on success, else negative errno.
+ */
+int usb_gadget_disconnect(struct usb_gadget *gadget)
+{
+ int ret;
+
+ mutex_lock(&gadget->udc->connect_lock);
+ ret = usb_gadget_disconnect_locked(gadget);
+ mutex_unlock(&gadget->udc->connect_lock);
+
+ return ret;
+}
EXPORT_SYMBOL_GPL(usb_gadget_disconnect);
/**
@@ -794,10 +829,11 @@ int usb_gadget_deactivate(struct usb_gadget *gadget)
if (gadget->deactivated)
goto out;
+ mutex_lock(&gadget->udc->connect_lock);
if (gadget->connected) {
- ret = usb_gadget_disconnect(gadget);
+ ret = usb_gadget_disconnect_locked(gadget);
if (ret)
- goto out;
+ goto unlock;
/*
* If gadget was being connected before deactivation, we want
@@ -807,6 +843,8 @@ int usb_gadget_deactivate(struct usb_gadget *gadget)
}
gadget->deactivated = true;
+unlock:
+ mutex_unlock(&gadget->udc->connect_lock);
out:
trace_usb_gadget_deactivate(gadget, ret);
@@ -830,6 +868,7 @@ int usb_gadget_activate(struct usb_gadget *gadget)
if (!gadget->deactivated)
goto out;
+ mutex_lock(&gadget->udc->connect_lock);
gadget->deactivated = false;
/*
@@ -837,7 +876,8 @@ int usb_gadget_activate(struct usb_gadget *gadget)
* while it was being deactivated, we call usb_gadget_connect().
*/
if (gadget->connected)
- ret = usb_gadget_connect(gadget);
+ ret = usb_gadget_connect_locked(gadget);
+ mutex_unlock(&gadget->udc->connect_lock);
out:
trace_usb_gadget_activate(gadget, ret);
@@ -1078,12 +1118,13 @@ EXPORT_SYMBOL_GPL(usb_gadget_set_state);
/* ------------------------------------------------------------------------- */
-static void usb_udc_connect_control(struct usb_udc *udc)
+/* Acquire connect_lock before calling this function. */
+static void usb_udc_connect_control_locked(struct usb_udc *udc) __must_hold(&udc->connect_lock)
{
- if (udc->vbus)
- usb_gadget_connect(udc->gadget);
+ if (udc->vbus && udc->started)
+ usb_gadget_connect_locked(udc->gadget);
else
- usb_gadget_disconnect(udc->gadget);
+ usb_gadget_disconnect_locked(udc->gadget);
}
/**
@@ -1099,10 +1140,12 @@ void usb_udc_vbus_handler(struct usb_gadget *gadget, bool status)
{
struct usb_udc *udc = gadget->udc;
+ mutex_lock(&udc->connect_lock);
if (udc) {
udc->vbus = status;
- usb_udc_connect_control(udc);
+ usb_udc_connect_control_locked(udc);
}
+ mutex_unlock(&udc->connect_lock);
}
EXPORT_SYMBOL_GPL(usb_udc_vbus_handler);
@@ -1124,7 +1167,7 @@ void usb_gadget_udc_reset(struct usb_gadget *gadget,
EXPORT_SYMBOL_GPL(usb_gadget_udc_reset);
/**
- * usb_gadget_udc_start - tells usb device controller to start up
+ * usb_gadget_udc_start_locked - tells usb device controller to start up
* @udc: The UDC to be started
*
* This call is issued by the UDC Class driver when it's about
@@ -1135,8 +1178,11 @@ EXPORT_SYMBOL_GPL(usb_gadget_udc_reset);
* necessary to have it powered on.
*
* Returns zero on success, else negative errno.
+ *
+ * Caller should acquire connect_lock before invoking this function.
*/
-static inline int usb_gadget_udc_start(struct usb_udc *udc)
+static inline int usb_gadget_udc_start_locked(struct usb_udc *udc)
+ __must_hold(&udc->connect_lock)
{
int ret;
@@ -1153,7 +1199,7 @@ static inline int usb_gadget_udc_start(struct usb_udc *udc)
}
/**
- * usb_gadget_udc_stop - tells usb device controller we don't need it anymore
+ * usb_gadget_udc_stop_locked - tells usb device controller we don't need it anymore
* @udc: The UDC to be stopped
*
* This call is issued by the UDC Class driver after calling
@@ -1162,8 +1208,11 @@ static inline int usb_gadget_udc_start(struct usb_udc *udc)
* The details are implementation specific, but it can go as
* far as powering off UDC completely and disable its data
* line pullups.
+ *
+ * Caller should acquire connect lock before invoking this function.
*/
-static inline void usb_gadget_udc_stop(struct usb_udc *udc)
+static inline void usb_gadget_udc_stop_locked(struct usb_udc *udc)
+ __must_hold(&udc->connect_lock)
{
if (!udc->started) {
dev_err(&udc->dev, "UDC had already stopped\n");
@@ -1322,6 +1371,7 @@ int usb_add_gadget(struct usb_gadget *gadget)
udc->gadget = gadget;
gadget->udc = udc;
+ mutex_init(&udc->connect_lock);
udc->started = false;
@@ -1523,11 +1573,15 @@ static int gadget_bind_driver(struct device *dev)
if (ret)
goto err_bind;
- ret = usb_gadget_udc_start(udc);
- if (ret)
+ mutex_lock(&udc->connect_lock);
+ ret = usb_gadget_udc_start_locked(udc);
+ if (ret) {
+ mutex_unlock(&udc->connect_lock);
goto err_start;
+ }
usb_gadget_enable_async_callbacks(udc);
- usb_udc_connect_control(udc);
+ usb_udc_connect_control_locked(udc);
+ mutex_unlock(&udc->connect_lock);
kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
return 0;
@@ -1558,12 +1612,14 @@ static void gadget_unbind_driver(struct device *dev)
kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
- usb_gadget_disconnect(gadget);
+ mutex_lock(&udc->connect_lock);
+ usb_gadget_disconnect_locked(gadget);
usb_gadget_disable_async_callbacks(udc);
if (gadget->irq)
synchronize_irq(gadget->irq);
udc->driver->unbind(gadget);
- usb_gadget_udc_stop(udc);
+ usb_gadget_udc_stop_locked(udc);
+ mutex_unlock(&udc->connect_lock);
mutex_lock(&udc_lock);
driver->is_bound = false;
@@ -1649,11 +1705,15 @@ static ssize_t soft_connect_store(struct device *dev,
}
if (sysfs_streq(buf, "connect")) {
- usb_gadget_udc_start(udc);
- usb_gadget_connect(udc->gadget);
+ mutex_lock(&udc->connect_lock);
+ usb_gadget_udc_start_locked(udc);
+ usb_gadget_connect_locked(udc->gadget);
+ mutex_unlock(&udc->connect_lock);
} else if (sysfs_streq(buf, "disconnect")) {
- usb_gadget_disconnect(udc->gadget);
- usb_gadget_udc_stop(udc);
+ mutex_lock(&udc->connect_lock);
+ usb_gadget_disconnect_locked(udc->gadget);
+ usb_gadget_udc_stop_locked(udc);
+ mutex_unlock(&udc->connect_lock);
} else {
dev_err(dev, "unsupported command '%s'\n", buf);
ret = -EINVAL;
base-commit: d629c0e221cd99198b843d8351a0a9bfec6c0423
--
2.40.0.577.gac1e443424-goog
From: Alexandr Sapozhnikov <alsp705(a)gmail.com>
[ Upstream commit 7245e629dcaaf308f1868aeffa218e9849c77893 ]
After having been compared to NULL value at cirrus.c:455, pointer
'pipe->plane.state->fb' is passed as 1st parameter in call to function
'cirrus_fb_blit_rect' at cirrus.c:461, where it is dereferenced at
cirrus.c:316.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
v2:
* aligned commit message to line-length limits
Signed-off-by: Alexandr Sapozhnikov <alsp705(a)gmail.com>
Reviewed-by: Thomas Zimmermann <tzimmermann(a)suse.de>
Signed-off-by: Thomas Zimmermann <tzimmermann(a)suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20230215171549.16305-1-alsp70…
Signed-off-by: Sasha Levin <sashal(a)kernel.org>
---
drivers/gpu/drm/tiny/cirrus.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/tiny/cirrus.c b/drivers/gpu/drm/tiny/cirrus.c
index 678c2ef1cae70..ffa7e61dd1835 100644
--- a/drivers/gpu/drm/tiny/cirrus.c
+++ b/drivers/gpu/drm/tiny/cirrus.c
@@ -455,7 +455,7 @@ static void cirrus_pipe_update(struct drm_simple_display_pipe *pipe,
if (state->fb && cirrus->cpp != cirrus_cpp(state->fb))
cirrus_mode_set(cirrus, &crtc->mode, state->fb);
- if (drm_atomic_helper_damage_merged(old_state, state, &rect))
+ if (state->fb && drm_atomic_helper_damage_merged(old_state, state, &rect))
cirrus_fb_blit_rect(state->fb, &shadow_plane_state->data[0], &rect);
}
--
2.39.2
I'm announcing the release of the 5.15.104 kernel.
All users of the 5.15 kernel series must upgrade.
The updated 5.15.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-5.15.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Documentation/filesystems/vfs.rst | 2
Makefile | 2
arch/riscv/include/asm/mmu.h | 2
arch/riscv/include/asm/tlbflush.h | 18
arch/riscv/mm/context.c | 40 -
arch/riscv/mm/tlbflush.c | 28 -
arch/s390/boot/ipl_report.c | 8
arch/s390/pci/pci.c | 16
arch/s390/pci/pci_bus.c | 12
arch/s390/pci/pci_bus.h | 3
arch/x86/kernel/cpu/mce/core.c | 1
arch/x86/kernel/cpu/resctrl/ctrlmondata.c | 7
arch/x86/kernel/cpu/resctrl/internal.h | 1
arch/x86/kernel/cpu/resctrl/rdtgroup.c | 25 +
arch/x86/kvm/vmx/nested.c | 10
arch/x86/mm/mem_encrypt_identity.c | 3
drivers/block/loop.c | 25 -
drivers/block/null_blk/main.c | 6
drivers/block/sunvdc.c | 2
drivers/clk/Kconfig | 2
drivers/cpuidle/cpuidle-psci-domain.c | 3
drivers/firmware/xilinx/zynqmp.c | 2
drivers/gpu/drm/amd/amdkfd/kfd_events.c | 9
drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c | 5
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 43 +-
drivers/gpu/drm/drm_gem_shmem_helper.c | 9
drivers/gpu/drm/i915/display/intel_display_types.h | 2
drivers/gpu/drm/i915/display/intel_psr.c | 207 +++++++---
drivers/gpu/drm/i915/gt/intel_ring.c | 2
drivers/gpu/drm/i915/i915_active.c | 24 -
drivers/gpu/drm/meson/meson_vpp.c | 2
drivers/gpu/drm/panfrost/panfrost_mmu.c | 2
drivers/gpu/drm/sun4i/sun4i_drv.c | 6
drivers/hid/hid-core.c | 18
drivers/hid/uhid.c | 1
drivers/hwmon/adt7475.c | 8
drivers/hwmon/ina3221.c | 2
drivers/hwmon/ltc2992.c | 1
drivers/hwmon/pmbus/adm1266.c | 1
drivers/hwmon/pmbus/ucd9000.c | 75 +++
drivers/hwmon/tmp513.c | 2
drivers/hwmon/xgene-hwmon.c | 1
drivers/interconnect/core.c | 4
drivers/interconnect/samsung/exynos.c | 6
drivers/media/i2c/m5mols/m5mols_core.c | 2
drivers/mmc/host/atmel-mci.c | 3
drivers/mmc/host/sdhci_am654.c | 2
drivers/net/bonding/bond_main.c | 23 -
drivers/net/dsa/mt7530.c | 64 +--
drivers/net/dsa/mv88e6xxx/chip.c | 16
drivers/net/ethernet/intel/i40e/i40e_main.c | 1
drivers/net/ethernet/intel/ice/ice.h | 14
drivers/net/ethernet/intel/ice/ice_main.c | 19
drivers/net/ethernet/intel/ice/ice_xsk.c | 4
drivers/net/ethernet/qlogic/qed/qed_dev.c | 5
drivers/net/ethernet/qlogic/qed/qed_mng_tlv.c | 2
drivers/net/ethernet/renesas/ravb_main.c | 12
drivers/net/ethernet/renesas/sh_eth.c | 12
drivers/net/ethernet/sun/ldmvsw.c | 3
drivers/net/ethernet/sun/sunvnet.c | 3
drivers/net/ipvlan/ipvlan_l3s.c | 1
drivers/net/phy/nxp-c45-tja11xx.c | 2
drivers/net/phy/smsc.c | 5
drivers/net/usb/smsc75xx.c | 7
drivers/nfc/pn533/usb.c | 1
drivers/nfc/st-nci/ndlc.c | 6
drivers/nvme/host/core.c | 28 -
drivers/nvme/host/pci.c | 2
drivers/nvme/target/core.c | 4
drivers/pci/bus.c | 21 +
drivers/pci/pci-driver.c | 4
drivers/pci/pci.c | 57 +-
drivers/pci/pci.h | 16
drivers/pci/pcie/dpc.c | 4
drivers/scsi/hosts.c | 3
drivers/scsi/mpt3sas/mpt3sas_transport.c | 14
drivers/tty/serial/8250/8250_em.c | 4
drivers/tty/serial/8250/8250_fsl.c | 4
drivers/tty/serial/fsl_lpuart.c | 12
drivers/vdpa/vdpa_sim/vdpa_sim.c | 13
drivers/video/fbdev/stifb.c | 27 +
fs/cifs/smb2inode.c | 31 +
fs/cifs/transport.c | 21 -
fs/ext4/inode.c | 18
fs/ext4/namei.c | 4
fs/ext4/super.c | 7
fs/ext4/xattr.c | 11
fs/jffs2/file.c | 15
include/drm/drm_bridge.h | 4
include/linux/hid.h | 3
include/linux/netdevice.h | 6
include/linux/pci.h | 1
include/linux/sh_intc.h | 5
include/linux/tracepoint.h | 15
io_uring/io_uring.c | 4
kernel/events/core.c | 2
kernel/trace/ftrace.c | 3
kernel/trace/trace.c | 2
kernel/trace/trace_events_hist.c | 3
kernel/trace/trace_hwlat.c | 3
mm/huge_memory.c | 6
net/9p/client.c | 2
net/ipv4/fib_frontend.c | 3
net/ipv4/ip_tunnel.c | 12
net/ipv4/tcp_output.c | 2
net/ipv6/ip6_tunnel.c | 4
net/iucv/iucv.c | 2
net/mptcp/pm_netlink.c | 16
net/mptcp/subflow.c | 12
net/netfilter/nft_masq.c | 2
net/netfilter/nft_nat.c | 2
net/netfilter/nft_redir.c | 4
net/smc/smc_cdc.c | 3
net/smc/smc_core.c | 2
net/xfrm/xfrm_state.c | 3
scripts/kconfig/confdata.c | 6
sound/hda/intel-dsp-config.c | 9
sound/pci/hda/hda_intel.c | 5
sound/pci/hda/patch_realtek.c | 1
tools/testing/selftests/net/devlink_port_split.py | 36 +
120 files changed, 919 insertions(+), 439 deletions(-)
Alex Hung (1):
drm/amd/display: fix shift-out-of-bounds in CalculateVMAndRowBytes
Alexandra Winter (1):
net/iucv: Fix size of interrupt data
Arınç ÜNAL (2):
net: dsa: mt7530: remove now incorrect comment regarding port 5
net: dsa: mt7530: set PLL frequency and trgmii only when trgmii is used
Baokun Li (3):
ext4: fail ext4_iget if special inode unallocated
ext4: update s_journal_inum if it changes after journal replay
ext4: fix task hung in ext4_xattr_delete_inode
Bard Liao (1):
ALSA: hda: intel-dsp-config: add MTL PCI id
Bart Van Assche (2):
scsi: core: Fix a procfs host directory removal regression
loop: Fix use-after-free issues
Biju Das (1):
serial: 8250_em: Fix UART port type
Bjorn Helgaas (1):
ALSA: hda: Match only Intel devices with CONTROLLER_IN_GPU()
Breno Leitao (1):
tcp: tcp_make_synack() can be called from process context
Budimir Markovic (1):
perf: Fix check before add_event_to_groups() in perf_group_detach()
Błażej Szczygieł (1):
drm/amd/pm: Fix sienna cichlid incorrect OD volage after resume
Chen Zhongjin (1):
ftrace: Fix invalid address access in lookup_rec() when index is 0
Christian Hewitt (1):
drm/meson: fix 1px pink line on GXM when scaling video overlay
D. Wythe (1):
net/smc: fix NULL sndbuf_desc in smc_cdc_tx_handler()
Damien Le Moal (2):
block: null_blk: Fix handling of fake timeout request
nvmet: avoid potential UAF in nvmet_req_complete()
Daniil Tatianin (2):
qed/qed_dev: guard against a possible division by zero
qed/qed_mng_tlv: correctly zero out ->min instead of ->hour
Dave Ertman (1):
ice: avoid bonding causing auxiliary plug/unplug under RTNL lock
David Hildenbrand (1):
mm/userfaultfd: propagate uffd-wp bit when PTE-mapping the huge zeropage
Dmitry Osipenko (2):
drm/panfrost: Don't sync rpm suspension after mmu flushing
drm/shmem-helper: Remove another errant put in error path
Elmer Miroslav Mosher Golovin (1):
nvme-pci: add NVME_QUIRK_BOGUS_NID for Netac NV3000
Eric Dumazet (1):
net: tunnels: annotate lockless accesses to dev->needed_headroom
Eric Van Hensbergen (1):
net/9p: fix bug in client create for .L
Eugenio Pérez (2):
vdpa_sim: not reset state in vdpasim_queue_ready
vdpa_sim: set last_used_idx as last_avail_idx in vdpasim_queue_ready
Fedor Pchelkin (2):
nfc: pn533: initialize struct pn533_out_arg properly
io_uring: avoid null-ptr-deref in io_arm_poll_handler
Francesco Dolcini (1):
mmc: sdhci_am654: lower power-on failed message severity
Geliang Tang (1):
mptcp: add ro_after_init for tcp{,v6}_prot_override
Glenn Washburn (1):
docs: Correct missing "d_" prefix for dentry_operations member d_weak_revalidate
Greg Kroah-Hartman (1):
Linux 5.15.104
Guo Ren (1):
riscv: asid: Fixup stale TLB entry cause application crash
Hamidreza H. Fard (1):
ALSA: hda/realtek: Fix the speaker output on Samsung Galaxy Book2 Pro
Heiner Kallweit (1):
net: phy: smsc: bail out in lan87xx_read_status if genphy_read_status fails
Helge Deller (1):
fbdev: stifb: Provide valid pixelclock and add fb_check_var() checks
Herbert Xu (1):
xfrm: Allow transport-mode states with AF_UNSPEC selector
Ido Schimmel (1):
ipv4: Fix incorrect table ID in IOCTL path
Ivan Vecera (1):
i40e: Fix kernel crash during reboot when adapter is in recovery mode
Janusz Krzysztofik (1):
drm/i915/active: Fix misuse of non-idle barriers as fence trackers
Jeremy Sowden (4):
netfilter: nft_nat: correct length for loading protocol registers
netfilter: nft_masq: correct length for loading protocol registers
netfilter: nft_redir: correct length for loading protocol registers
netfilter: nft_redir: correct value of inet type `.maxattrs`
Jianguo Wu (1):
ipvlan: Make skb->skb_iif track skb->dev for l3s mode
Johan Hovold (4):
serial: 8250_fsl: fix handle_irq locking
interconnect: fix mem leak when freeing nodes
interconnect: exynos: fix node leak in probe PM QoS error path
drm/sun4i: fix missing component unbind on bind errors
John Harrison (1):
drm/i915: Don't use stolen memory for ring buffers with LLC
José Roberto de Souza (3):
drm/i915/display: Workaround cursor left overs with PSR2 selective fetch enabled
drm/i915/display/psr: Use drm damage helpers to calculate plane damaged area
drm/i915/display/psr: Handle plane and pipe restrictions at every page flip
Jouni Högander (1):
drm/i915/psr: Use calculated io and fast wake lines
Jurica Vukadin (1):
kconfig: Update config changed flag before calling callback
Krzysztof Kozlowski (1):
hwmon: tmp512: drop of_match_ptr for ID table
Lars-Peter Clausen (3):
hwmon: (ucd90320) Add minimum delay between bus accesses
hwmon: (adm1266) Set `can_sleep` flag for GPIO chip
hwmon: (ltc2992) Set `can_sleep` flag for GPIO chip
Lee Jones (2):
HID: core: Provide new max_buffer_size attribute to over-ride the default
HID: uhid: Over-ride the default maximum data buffer value with our own
Liang He (2):
block: sunvdc: add check for mdesc_grab() returning NULL
ethernet: sun: add check for the mdesc_grab()
Linus Torvalds (1):
media: m5mols: fix off-by-one loop termination error
Liu Ying (1):
drm/bridge: Fix returned array size name for atomic_get_input_bus_fmts kdoc
Lukas Wunner (2):
PCI: Unify delay handling for reset and resume
PCI/DPC: Await readiness of secondary bus after reset
Maciej Fijalkowski (1):
ice: xsk: disable txq irq before flushing hw
Marcus Folkesson (1):
hwmon: (ina3221) return prober error code
Matthieu Baerts (1):
mptcp: avoid setting TCP_CLOSE state twice
Michael Karcher (1):
sh: intc: Avoid spurious sizeof-pointer-div warning
Ming Lei (1):
nvme: fix handling single range discard request
Nikita Zhandarovich (1):
x86/mm: Fix use of uninitialized buffer in sme_enable()
Niklas Schnelle (1):
PCI: s390: Fix use-after-free of PCI resources with per-function hotplug
Nikolay Aleksandrov (2):
bonding: restore IFF_MASTER/SLAVE flags on bond enslave ether type change
bonding: restore bond's IFF_SLAVE flag if a non-eth dev enslave fails
Paolo Abeni (2):
mptcp: fix possible deadlock in subflow_error_report
mptcp: fix lockdep false positive in mptcp_pm_nl_create_listen_socket()
Paolo Bonzini (1):
KVM: nVMX: add missing consistency checks for CR0 and CR4
Po-Hsu Lin (1):
selftests: net: devlink_port_split.py: skip test if no suitable device available
Qu Huang (1):
drm/amdkfd: Fix an illegal memory access
Radu Pirea (OSS) (1):
net: phy: nxp-c45-tja11xx: fix MII_BASIC_CONFIG_REV bit
Randy Dunlap (1):
clk: HI655X: select REGMAP instead of depending on it
Roman Gushchin (1):
firmware: xilinx: don't make a sleepable memory allocation from an atomic context
Sergey Matyukevich (1):
Revert "riscv: mm: notify remote harts about mmu cache updates"
Shawn Guo (1):
cpuidle: psci: Iterate backwards over list in psci_pd_remove()
Shawn Wang (1):
x86/resctrl: Clear staged_config[] before and after it is used
Sherry Sun (1):
tty: serial: fsl_lpuart: skip waiting for transmission complete when UARTCTRL_SBK is asserted
Steven Rostedt (Google) (2):
tracing: Check field value in hist_field_name()
tracing: Make tracepoint lockdep check actually test something
Sung-hun Kim (1):
tracing: Make splice_read available again
Sven Schnelle (1):
s390/ipl: add missing intersection check to ipl_report handling
Szymon Heidrich (2):
net: usb: smsc75xx: Limit packet length to skb->len
net: usb: smsc75xx: Move packet length check to prevent kernel panic in skb_pull
Tero Kristo (1):
trace/hwlat: Do not wipe the contents of per-cpu thread data
Theodore Ts'o (1):
ext4: fix possible double unlock when moving a directory
Tobias Schramm (1):
mmc: atmel-mci: fix race between stop command and start of next command
Tom Rix (1):
drm/i915/display: clean up comments
Tony O'Brien (2):
hwmon: (adt7475) Display smoothing attributes in correct order
hwmon: (adt7475) Fix masking of hysteresis registers
Vladimir Oltean (1):
net: dsa: mv88e6xxx: fix max_mtu of 1492 on 6165, 6191, 6220, 6250, 6290
Volker Lendecke (1):
cifs: Fix smb2_set_path_size()
Wenchao Hao (1):
scsi: mpt3sas: Fix NULL pointer access in mpt3sas_transport_port_add()
Wenjia Zhang (1):
net/smc: fix deadlock triggered by cancel_delayed_work_syn()
Wolfram Sang (2):
ravb: avoid PHY being resumed when interface is not up
sh_eth: avoid PHY being resumed when interface is not up
Yazen Ghannam (1):
x86/mce: Make sure logged MCEs are processed after sysfs update
Yifei Liu (1):
jffs2: correct logic when creating a hole in jffs2_write_begin
Zhang Xiaoxu (1):
cifs: Move the in_send statistic to __smb_send_rqst()
Zheng Wang (2):
nfc: st-nci: Fix use after free bug in ndlc_remove due to race condition
hwmon: (xgene) Fix use after free bug in xgene_hwmon_remove due to race condition
From: Roberto Sassu <roberto.sassu(a)huawei.com>
Changelog:
v4:
- Replace sg_init_table()/sg_set_buf() with sg_init_one() (suggested by
Eric)
v3:
v2:
- Add patch by Herbert to take only the needed bytes for a MPI from the
scatterlist
- Use only one scatterlist for signature and digest (suggested by Eric)
- Rename key variable to buf (suggested by Eric)
- Rename key_max_len variable to buf_len
- Use size_t for the buf_len variable instead of u32
v1:
- Unconditionally copy the signature and digest to the buffer to keep the
code simple (suggested by Eric)
Herbert Xu (1):
lib/mpi: Fix buffer overrun when SG is too long
Roberto Sassu (1):
KEYS: asymmetric: Copy sig and digest in public_key_verify_signature()
crypto/asymmetric_keys/public_key.c | 38 ++++++++++++++++-------------
lib/mpi/mpicoder.c | 3 ++-
2 files changed, 23 insertions(+), 18 deletions(-)
--
2.25.1
When the host tries to remove a PCI device, the host first sends a
PCI_EJECT message to the guest, and the guest is supposed to gracefully
remove the PCI device and send a PCI_EJECTION_COMPLETE message to the host;
the host then sends a VMBus message CHANNELMSG_RESCIND_CHANNELOFFER to
the guest (when the guest receives this message, the device is already
unassigned from the guest) and the guest can do some final cleanup work;
if the guest fails to respond to the PCI_EJECT message within one minute,
the host sends the VMBus message CHANNELMSG_RESCIND_CHANNELOFFER and
removes the PCI device forcibly.
In the case of fast device addition/removal, it's possible that the PCI
device driver is still configuring MSI-X interrupts when the guest receives
the PCI_EJECT message; the channel callback calls hv_pci_eject_device(),
which sets hpdev->state to hv_pcichild_ejecting, and schedules a work
hv_eject_device_work(); if the PCI device driver is calling
pci_alloc_irq_vectors() -> ... -> hv_compose_msi_msg(), we can break the
while loop in hv_compose_msi_msg() due to the updated hpdev->state, and
leave data->chip_data with its default value of NULL; later, when the PCI
device driver calls request_irq() -> ... -> hv_irq_unmask(), the guest
crashes in hv_arch_irq_unmask() due to data->chip_data being NULL.
Fix the issue by not testing hpdev->state in the while loop: when the
guest receives PCI_EJECT, the device is still assigned to the guest, and
the guest has one minute to finish the device removal gracefully. We don't
really need to (and we should not) test hpdev->state in the loop.
Fixes: de0aa7b2f97d ("PCI: hv: Fix 2 hang issues in hv_compose_msi_msg()")
Signed-off-by: Dexuan Cui <decui(a)microsoft.com>
Reviewed-by: Michael Kelley <mikelley(a)microsoft.com>
Cc: stable(a)vger.kernel.org
---
v2:
Removed the "debug code".
No change to the patch body.
Added Cc:stable
v3:
Added Michael's Reviewed-by.
drivers/pci/controller/pci-hyperv.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
index b82c7cde19e66..1b11cf7391933 100644
--- a/drivers/pci/controller/pci-hyperv.c
+++ b/drivers/pci/controller/pci-hyperv.c
@@ -643,6 +643,11 @@ static void hv_arch_irq_unmask(struct irq_data *data)
pbus = pdev->bus;
hbus = container_of(pbus->sysdata, struct hv_pcibus_device, sysdata);
int_desc = data->chip_data;
+ if (!int_desc) {
+ dev_warn(&hbus->hdev->device, "%s() can not unmask irq %u\n",
+ __func__, data->irq);
+ return;
+ }
spin_lock_irqsave(&hbus->retarget_msi_interrupt_lock, flags);
@@ -1911,12 +1916,6 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
hv_pci_onchannelcallback(hbus);
spin_unlock_irqrestore(&channel->sched_lock, flags);
- if (hpdev->state == hv_pcichild_ejecting) {
- dev_err_once(&hbus->hdev->device,
- "the device is being ejected\n");
- goto enable_tasklet;
- }
-
udelay(100);
}
--
2.25.1
In the case of fast device addition/removal, it's possible that
hv_eject_device_work() can start to run before create_root_hv_pci_bus()
starts to run; as a result, the pci_get_domain_bus_and_slot() in
hv_eject_device_work() can return a 'pdev' of NULL, and
hv_eject_device_work() can remove the 'hpdev', and immediately send a
message PCI_EJECTION_COMPLETE to the host, and the host immediately
unassigns the PCI device from the guest; meanwhile,
create_root_hv_pci_bus() and the PCI device driver can be probing the
dead PCI device and reporting timeout errors.
Fix the issue by adding a per-bus mutex 'state_lock' and grabbing the
mutex before powering on the PCI bus in hv_pci_enter_d0(): when
hv_eject_device_work() starts to run, it's able to find the 'pdev' and call
pci_stop_and_remove_bus_device(pdev): if the PCI device driver has
loaded, the PCI device driver's probe() function is already called in
create_root_hv_pci_bus() -> pci_bus_add_devices(), and now
hv_eject_device_work() -> pci_stop_and_remove_bus_device() is able
to call the PCI device driver's remove() function and remove the device
reliably; if the PCI device driver hasn't loaded yet, the function call
hv_eject_device_work() -> pci_stop_and_remove_bus_device() is able to
remove the PCI device reliably and the PCI device driver's probe()
function won't be called; if the PCI device driver's probe() is already
running (e.g., systemd-udev is loading the PCI device driver), it must
be holding the per-device lock, and after the probe() finishes and releases
the lock, hv_eject_device_work() -> pci_stop_and_remove_bus_device() is
able to proceed to remove the device reliably.
Fixes: 4daace0d8ce8 ("PCI: hv: Add paravirtual PCI front-end for Microsoft Hyper-V VMs")
Signed-off-by: Dexuan Cui <decui(a)microsoft.com>
Reviewed-by: Michael Kelley <mikelley(a)microsoft.com>
Cc: stable(a)vger.kernel.org
---
v2:
Removed the "debug code".
Fixed the "goto out" in hv_pci_resume() [Michael Kelley]
Added Cc:stable
v3:
Added Michael's Reviewed-by.
drivers/pci/controller/pci-hyperv.c | 29 ++++++++++++++++++++++++++---
1 file changed, 26 insertions(+), 3 deletions(-)
diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
index 48feab095a144..3ae2f99dea8c2 100644
--- a/drivers/pci/controller/pci-hyperv.c
+++ b/drivers/pci/controller/pci-hyperv.c
@@ -489,7 +489,10 @@ struct hv_pcibus_device {
struct fwnode_handle *fwnode;
/* Protocol version negotiated with the host */
enum pci_protocol_version_t protocol_version;
+
+ struct mutex state_lock;
enum hv_pcibus_state state;
+
struct hv_device *hdev;
resource_size_t low_mmio_space;
resource_size_t high_mmio_space;
@@ -2512,6 +2515,8 @@ static void pci_devices_present_work(struct work_struct *work)
if (!dr)
return;
+ mutex_lock(&hbus->state_lock);
+
/* First, mark all existing children as reported missing. */
spin_lock_irqsave(&hbus->device_list_lock, flags);
list_for_each_entry(hpdev, &hbus->children, list_entry) {
@@ -2593,6 +2598,8 @@ static void pci_devices_present_work(struct work_struct *work)
break;
}
+ mutex_unlock(&hbus->state_lock);
+
kfree(dr);
}
@@ -2741,6 +2748,8 @@ static void hv_eject_device_work(struct work_struct *work)
hpdev = container_of(work, struct hv_pci_dev, wrk);
hbus = hpdev->hbus;
+ mutex_lock(&hbus->state_lock);
+
/*
* Ejection can come before or after the PCI bus has been set up, so
* attempt to find it and tear down the bus state, if it exists. This
@@ -2777,6 +2786,8 @@ static void hv_eject_device_work(struct work_struct *work)
put_pcichild(hpdev);
put_pcichild(hpdev);
/* hpdev has been freed. Do not use it any more. */
+
+ mutex_unlock(&hbus->state_lock);
}
/**
@@ -3562,6 +3573,7 @@ static int hv_pci_probe(struct hv_device *hdev,
return -ENOMEM;
hbus->bridge = bridge;
+ mutex_init(&hbus->state_lock);
hbus->state = hv_pcibus_init;
hbus->wslot_res_allocated = -1;
@@ -3670,9 +3682,11 @@ static int hv_pci_probe(struct hv_device *hdev,
if (ret)
goto free_irq_domain;
+ mutex_lock(&hbus->state_lock);
+
ret = hv_pci_enter_d0(hdev);
if (ret)
- goto free_irq_domain;
+ goto release_state_lock;
ret = hv_pci_allocate_bridge_windows(hbus);
if (ret)
@@ -3690,12 +3704,15 @@ static int hv_pci_probe(struct hv_device *hdev,
if (ret)
goto free_windows;
+ mutex_unlock(&hbus->state_lock);
return 0;
free_windows:
hv_pci_free_bridge_windows(hbus);
exit_d0:
(void) hv_pci_bus_exit(hdev, true);
+release_state_lock:
+ mutex_unlock(&hbus->state_lock);
free_irq_domain:
irq_domain_remove(hbus->irq_domain);
free_fwnode:
@@ -3945,20 +3962,26 @@ static int hv_pci_resume(struct hv_device *hdev)
if (ret)
goto out;
+ mutex_lock(&hbus->state_lock);
+
ret = hv_pci_enter_d0(hdev);
if (ret)
- goto out;
+ goto release_state_lock;
ret = hv_send_resources_allocated(hdev);
if (ret)
- goto out;
+ goto release_state_lock;
prepopulate_bars(hbus);
hv_pci_restore_msi_state(hbus);
hbus->state = hv_pcibus_installed;
+ mutex_unlock(&hbus->state_lock);
return 0;
+
+release_state_lock:
+ mutex_unlock(&hbus->state_lock);
out:
vmbus_close(hdev->channel);
return ret;
--
2.25.1
This reverts commit d6af2ed29c7c1c311b96dac989dcb991e90ee195.
The statement "the hv_pci_bus_exit() call releases structures of all its
child devices" in commit d6af2ed29c7c is not true: in the path
hv_pci_probe() -> hv_pci_enter_d0() -> hv_pci_bus_exit(hdev, true): the
parameter "keep_devs" is true, so hv_pci_bus_exit() does *not* release the
child "struct hv_pci_dev *hpdev" that is created earlier in
pci_devices_present_work() -> new_pcichild_device().
The commit d6af2ed29c7c was originally made in July 2020 for RHEL 7.7,
where the old version of hv_pci_bus_exit() was used; when the commit was
rebased and merged into the upstream, people didn't notice that it's
not really necessary. The commit itself doesn't cause any issue, but it
makes hv_pci_probe() more complicated. Revert it to facilitate some
upcoming changes to hv_pci_probe().
Signed-off-by: Dexuan Cui <decui(a)microsoft.com>
Reviewed-by: Michael Kelley <mikelley(a)microsoft.com>
Acked-by: Wei Hu <weh(a)microsoft.com>
Cc: stable(a)vger.kernel.org
---
v2:
No change to the patch body.
Added Wei Hu's Acked-by.
Added Cc:stable
v3:
Added Michael's Reviewed-by.
drivers/pci/controller/pci-hyperv.c | 71 ++++++++++++++---------------
1 file changed, 34 insertions(+), 37 deletions(-)
diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
index 46df6d093d683..48feab095a144 100644
--- a/drivers/pci/controller/pci-hyperv.c
+++ b/drivers/pci/controller/pci-hyperv.c
@@ -3225,8 +3225,10 @@ static int hv_pci_enter_d0(struct hv_device *hdev)
struct pci_bus_d0_entry *d0_entry;
struct hv_pci_compl comp_pkt;
struct pci_packet *pkt;
+ bool retry = true;
int ret;
+enter_d0_retry:
/*
* Tell the host that the bus is ready to use, and moved into the
* powered-on state. This includes telling the host which region
@@ -3253,6 +3255,38 @@ static int hv_pci_enter_d0(struct hv_device *hdev)
if (ret)
goto exit;
+ /*
+ * In certain case (Kdump) the pci device of interest was
+ * not cleanly shut down and resource is still held on host
+ * side, the host could return invalid device status.
+ * We need to explicitly request host to release the resource
+ * and try to enter D0 again.
+ */
+ if (comp_pkt.completion_status < 0 && retry) {
+ retry = false;
+
+ dev_err(&hdev->device, "Retrying D0 Entry\n");
+
+ /*
+ * Hv_pci_bus_exit() calls hv_send_resource_released()
+ * to free up resources of its child devices.
+ * In the kdump kernel we need to set the
+ * wslot_res_allocated to 255 so it scans all child
+ * devices to release resources allocated in the
+ * normal kernel before panic happened.
+ */
+ hbus->wslot_res_allocated = 255;
+
+ ret = hv_pci_bus_exit(hdev, true);
+
+ if (ret == 0) {
+ kfree(pkt);
+ goto enter_d0_retry;
+ }
+ dev_err(&hdev->device,
+ "Retrying D0 failed with ret %d\n", ret);
+ }
+
if (comp_pkt.completion_status < 0) {
dev_err(&hdev->device,
"PCI Pass-through VSP failed D0 Entry with status %x\n",
@@ -3493,7 +3527,6 @@ static int hv_pci_probe(struct hv_device *hdev,
struct hv_pcibus_device *hbus;
u16 dom_req, dom;
char *name;
- bool enter_d0_retry = true;
int ret;
/*
@@ -3633,47 +3666,11 @@ static int hv_pci_probe(struct hv_device *hdev,
if (ret)
goto free_fwnode;
-retry:
ret = hv_pci_query_relations(hdev);
if (ret)
goto free_irq_domain;
ret = hv_pci_enter_d0(hdev);
- /*
- * In certain case (Kdump) the pci device of interest was
- * not cleanly shut down and resource is still held on host
- * side, the host could return invalid device status.
- * We need to explicitly request host to release the resource
- * and try to enter D0 again.
- * Since the hv_pci_bus_exit() call releases structures
- * of all its child devices, we need to start the retry from
- * hv_pci_query_relations() call, requesting host to send
- * the synchronous child device relations message before this
- * information is needed in hv_send_resources_allocated()
- * call later.
- */
- if (ret == -EPROTO && enter_d0_retry) {
- enter_d0_retry = false;
-
- dev_err(&hdev->device, "Retrying D0 Entry\n");
-
- /*
- * Hv_pci_bus_exit() calls hv_send_resources_released()
- * to free up resources of its child devices.
- * In the kdump kernel we need to set the
- * wslot_res_allocated to 255 so it scans all child
- * devices to release resources allocated in the
- * normal kernel before panic happened.
- */
- hbus->wslot_res_allocated = 255;
- ret = hv_pci_bus_exit(hdev, true);
-
- if (ret == 0)
- goto retry;
-
- dev_err(&hdev->device,
- "Retrying D0 failed with ret %d\n", ret);
- }
if (ret)
goto free_irq_domain;
--
2.25.1