public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable@vger.kernel.org, Johan Hovold <johan@kernel.org>,
	Sasha Levin <sashal@kernel.org>
Subject: [PATCH 4.14 11/29] USB: serial: digi_acceleport: fix write-wakeup deadlocks
Date: Thu,  7 Jan 2021 15:31:26 +0100	[thread overview]
Message-ID: <20210107143054.549193648@linuxfoundation.org> (raw)
In-Reply-To: <20210107143052.973437064@linuxfoundation.org>

From: Johan Hovold <johan@kernel.org>

[ Upstream commit 5098e77962e7c8947f87bd8c5869c83e000a522a ]

The driver must not call tty_wakeup() while holding its private lock as
line disciplines are allowed to call back into write() from
write_wakeup(), leading to a deadlock.

Also remove the unneeded work struct that was used to defer wakeup in
order to work around a possible race in ancient times (see comment about
n_tty write_chan() in commit 14b54e39b412 ("USB: serial: remove
changelogs and old todo entries")).

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/usb/serial/digi_acceleport.c | 45 ++++++++--------------------
 1 file changed, 13 insertions(+), 32 deletions(-)

diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 2ce39af32cfa6..e494ffdc06bc9 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -23,7 +23,6 @@
 #include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <linux/workqueue.h>
 #include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/wait.h>
@@ -202,14 +201,12 @@ struct digi_port {
 	int dp_throttle_restart;
 	wait_queue_head_t dp_flush_wait;
 	wait_queue_head_t dp_close_wait;	/* wait queue for close */
-	struct work_struct dp_wakeup_work;
 	struct usb_serial_port *dp_port;
 };
 
 
 /* Local Function Declarations */
 
-static void digi_wakeup_write_lock(struct work_struct *work);
 static int digi_write_oob_command(struct usb_serial_port *port,
 	unsigned char *buf, int count, int interruptible);
 static int digi_write_inb_command(struct usb_serial_port *port,
@@ -360,26 +357,6 @@ __releases(lock)
 	return timeout;
 }
 
-
-/*
- *  Digi Wakeup Write
- *
- *  Wake up port, line discipline, and tty processes sleeping
- *  on writes.
- */
-
-static void digi_wakeup_write_lock(struct work_struct *work)
-{
-	struct digi_port *priv =
-			container_of(work, struct digi_port, dp_wakeup_work);
-	struct usb_serial_port *port = priv->dp_port;
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->dp_port_lock, flags);
-	tty_port_tty_wakeup(&port->port);
-	spin_unlock_irqrestore(&priv->dp_port_lock, flags);
-}
-
 /*
  *  Digi Write OOB Command
  *
@@ -990,6 +967,7 @@ static void digi_write_bulk_callback(struct urb *urb)
 	struct digi_serial *serial_priv;
 	int ret = 0;
 	int status = urb->status;
+	bool wakeup;
 
 	/* port and serial sanity check */
 	if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) {
@@ -1016,6 +994,7 @@ static void digi_write_bulk_callback(struct urb *urb)
 	}
 
 	/* try to send any buffered data on this port */
+	wakeup = true;
 	spin_lock(&priv->dp_port_lock);
 	priv->dp_write_urb_in_use = 0;
 	if (priv->dp_out_buf_len > 0) {
@@ -1031,19 +1010,18 @@ static void digi_write_bulk_callback(struct urb *urb)
 		if (ret == 0) {
 			priv->dp_write_urb_in_use = 1;
 			priv->dp_out_buf_len = 0;
+			wakeup = false;
 		}
 	}
-	/* wake up processes sleeping on writes immediately */
-	tty_port_tty_wakeup(&port->port);
-	/* also queue up a wakeup at scheduler time, in case we */
-	/* lost the race in write_chan(). */
-	schedule_work(&priv->dp_wakeup_work);
-
 	spin_unlock(&priv->dp_port_lock);
+
 	if (ret && ret != -EPERM)
 		dev_err_console(port,
 			"%s: usb_submit_urb failed, ret=%d, port=%d\n",
 			__func__, ret, priv->dp_port_num);
+
+	if (wakeup)
+		tty_port_tty_wakeup(&port->port);
 }
 
 static int digi_write_room(struct tty_struct *tty)
@@ -1243,7 +1221,6 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num)
 	init_waitqueue_head(&priv->dp_transmit_idle_wait);
 	init_waitqueue_head(&priv->dp_flush_wait);
 	init_waitqueue_head(&priv->dp_close_wait);
-	INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock);
 	priv->dp_port = port;
 
 	init_waitqueue_head(&port->write_wait);
@@ -1510,13 +1487,14 @@ static int digi_read_oob_callback(struct urb *urb)
 			rts = C_CRTSCTS(tty);
 
 		if (tty && opcode == DIGI_CMD_READ_INPUT_SIGNALS) {
+			bool wakeup = false;
+
 			spin_lock(&priv->dp_port_lock);
 			/* convert from digi flags to termiox flags */
 			if (val & DIGI_READ_INPUT_SIGNALS_CTS) {
 				priv->dp_modem_signals |= TIOCM_CTS;
-				/* port must be open to use tty struct */
 				if (rts)
-					tty_port_tty_wakeup(&port->port);
+					wakeup = true;
 			} else {
 				priv->dp_modem_signals &= ~TIOCM_CTS;
 				/* port must be open to use tty struct */
@@ -1535,6 +1513,9 @@ static int digi_read_oob_callback(struct urb *urb)
 				priv->dp_modem_signals &= ~TIOCM_CD;
 
 			spin_unlock(&priv->dp_port_lock);
+
+			if (wakeup)
+				tty_port_tty_wakeup(&port->port);
 		} else if (opcode == DIGI_CMD_TRANSMIT_IDLE) {
 			spin_lock(&priv->dp_port_lock);
 			priv->dp_transmit_idle = 1;
-- 
2.27.0




  parent reply	other threads:[~2021-01-07 14:31 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-07 14:31 [PATCH 4.14 00/29] 4.14.214-rc1 review Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 01/29] x86/entry/64: Add instruction suffix Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 02/29] md/raid10: initialize r10_bio->read_slot before use Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 03/29] ALSA: hda/ca0132 - Fix work handling in delayed HP detection Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 04/29] ALSA: usb-audio: simplify set_sync_ep_implicit_fb_quirk Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 05/29] ALSA: usb-audio: fix sync-ep altsetting sanity check Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 06/29] mm: memcontrol: eliminate raw access to stat and event counters Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 07/29] mm: memcontrol: implement lruvec stat functions on top of each other Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 08/29] mm: memcontrol: fix excessive complexity in memory.stat reporting Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 09/29] vfio/pci: Move dummy_resources_list init in vfio_pci_probe() Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 10/29] s390/dasd: fix hanging device offline processing Greg Kroah-Hartman
2021-01-07 14:31 ` Greg Kroah-Hartman [this message]
2021-01-07 14:31 ` [PATCH 4.14 12/29] powerpc/bitops: Fix possible undefined behaviour with fls() and fls64() Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 13/29] uapi: move constants from <linux/kernel.h> to <linux/const.h> Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 14/29] of: fix linker-section match-table corruption Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 15/29] reiserfs: add check for an invalid ih_entry_count Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 16/29] misc: vmw_vmci: fix kernel info-leak by initializing dbells in vmci_ctx_get_chkpt_doorbells() Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 17/29] media: gp8psk: initialize stats at power control logic Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 18/29] ALSA: seq: Use bool for snd_seq_queue internal flags Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 19/29] rtc: sun6i: Fix memleak in sun6i_rtc_clk_init Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 20/29] module: set MODULE_STATE_GOING state when a module fails to load Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 21/29] quota: Dont overflow quota file offsets Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 22/29] powerpc: sysdev: add missing iounmap() on error in mpic_msgr_probe() Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 23/29] module: delay kobject uevent until after module init call Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 24/29] ALSA: pcm: Clear the full allocated memory at hw_params Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 25/29] dm verity: skip verity work if I/O error when system is shutting down Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 26/29] kdev_t: always inline major/minor helper functions Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 27/29] iio:imu:bmi160: Fix alignment and data leak issues Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 28/29] iio:magnetometer:mag3110: " Greg Kroah-Hartman
2021-01-07 14:31 ` [PATCH 4.14 29/29] mwifiex: Fix possible buffer overflows in mwifiex_cmd_802_11_ad_hoc_start Greg Kroah-Hartman
2021-01-08  7:35 ` [PATCH 4.14 00/29] 4.14.214-rc1 review Naresh Kamboju
2021-01-08 17:38 ` Guenter Roeck

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210107143054.549193648@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=johan@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=sashal@kernel.org \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox