* [PATCH v2 01/12] USB: serial: io_edgeport: fix NULL-deref on early status
[not found] <20261023121530.186541-1-johan@kernel.org>
@ 2026-10-23 12:15 ` Johan Hovold
2026-10-23 12:15 ` [PATCH v2 02/12] USB: serial: io_edgeport: fix potential close() use-after-free Johan Hovold
` (5 subsequent siblings)
6 siblings, 0 replies; 7+ messages in thread
From: Johan Hovold @ 2026-10-23 12:15 UTC (permalink / raw)
To: Johan Hovold; +Cc: linux-usb, linux-kernel, syzbot+763813d65c7e18c1b6d5, stable
The driver submits the interrupt-in URB during probe or on first port
open, which on completion may submit the bulk-in URB before all ports
have been opened and their waitqueues have been initialised.
If a (malicious) device sends a status message for a port that has not
yet been opened this may lead to a NULL-pointer dereference in the
bulk-in completion handler when attempting to wakeup blocked tasks.
Move waitqueue initialisation from open() to port_probe() to address
this.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reported-by: syzbot+763813d65c7e18c1b6d5@syzkaller.appspotmail.com
Link: https://lore.kernel.org/6a8818d8.ae6ddae5.3da009.0031.GAE@google.com
Cc: stable@vger.kernel.org
Signed-off-by: Johan Hovold <johan@kernel.org>
---
drivers/usb/serial/io_edgeport.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index eaa8f00716c8..cdf41e86ba44 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -877,11 +877,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
}
}
- /* initialize our wait queues */
- init_waitqueue_head(&edge_port->wait_open);
- init_waitqueue_head(&edge_port->wait_chase);
- init_waitqueue_head(&edge_port->wait_command);
-
/* initialize our port settings */
edge_port->txCredits = 0; /* Can't send any data yet */
/* Must always set this bit to enable ints! */
@@ -2965,6 +2960,11 @@ static int edge_port_probe(struct usb_serial_port *port)
return -ENOMEM;
spin_lock_init(&edge_port->ep_lock);
+
+ init_waitqueue_head(&edge_port->wait_open);
+ init_waitqueue_head(&edge_port->wait_chase);
+ init_waitqueue_head(&edge_port->wait_command);
+
edge_port->port = port;
usb_set_serial_port_data(port, edge_port);
--
2.55.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 02/12] USB: serial: io_edgeport: fix potential close() use-after-free
[not found] <20261023121530.186541-1-johan@kernel.org>
2026-10-23 12:15 ` [PATCH v2 01/12] USB: serial: io_edgeport: fix NULL-deref on early status Johan Hovold
@ 2026-10-23 12:15 ` Johan Hovold
2026-10-23 12:15 ` [PATCH v2 03/12] USB: serial: io_edgeport: fix potential NULL-deref at open Johan Hovold
` (4 subsequent siblings)
6 siblings, 0 replies; 7+ messages in thread
From: Johan Hovold @ 2026-10-23 12:15 UTC (permalink / raw)
To: Johan Hovold; +Cc: linux-usb, linux-kernel, stable
Add the missing open check on write() and locking when updating the port
status during close() to prevent a racing interrupt completion handler
from trying to submit more data for the port while its write URB and
FIFO are being deallocated.
This issue was flagged by Sashiko when reviewing a related fix.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Link: https://sashiko.dev/#/patchset/20260714101316.823942-1-shpark061104%40gmail.com?part=1
Signed-off-by: Johan Hovold <johan@kernel.org>
---
drivers/usb/serial/io_edgeport.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index cdf41e86ba44..a5011fa91ee7 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -1085,7 +1085,9 @@ static void edge_close(struct usb_serial_port *port)
/* port->close = true; */
edge_port->closePending = false;
+ spin_lock_irq(&edge_port->ep_lock);
edge_port->open = false;
+ spin_unlock_irq(&edge_port->ep_lock);
edge_port->openPending = false;
usb_kill_urb(edge_port->write_urb);
@@ -1127,6 +1129,12 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
spin_lock_irqsave(&edge_port->ep_lock, flags);
+ /* avoid accessing freed fifo if tty_wakeup() races with close() */
+ if (!edge_port->open) {
+ spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+ return 0;
+ }
+
/* calculate number of bytes to put in fifo */
copySize = min_t(unsigned int, count,
(edge_port->txCredits - fifo->count));
--
2.55.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 03/12] USB: serial: io_edgeport: fix potential NULL-deref at open
[not found] <20261023121530.186541-1-johan@kernel.org>
2026-10-23 12:15 ` [PATCH v2 01/12] USB: serial: io_edgeport: fix NULL-deref on early status Johan Hovold
2026-10-23 12:15 ` [PATCH v2 02/12] USB: serial: io_edgeport: fix potential close() use-after-free Johan Hovold
@ 2026-10-23 12:15 ` Johan Hovold
2026-10-23 12:15 ` [PATCH v2 04/12] USB: serial: io_edgeport: move initial termios update to open() Johan Hovold
` (3 subsequent siblings)
6 siblings, 0 replies; 7+ messages in thread
From: Johan Hovold @ 2026-10-23 12:15 UTC (permalink / raw)
To: Johan Hovold; +Cc: linux-usb, linux-kernel, stable
Do not mark the port as open until after the write FIFO has been
allocated and initialised to prevent a racing interrupt completion from
attempting to send stale data and dereference the FIFO buffer pointer.
Note that the open flag defaults to false and is cleared on close() so
there is no need to reinitialise it on every open().
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Johan Hovold <johan@kernel.org>
---
drivers/usb/serial/io_edgeport.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index a5011fa91ee7..e8e641e9a197 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -885,9 +885,7 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
/* send a open port command */
edge_port->openPending = true;
- edge_port->open = false;
response = send_iosp_ext_cmd(edge_port, IOSP_CMD_OPEN_PORT, 0);
-
if (response < 0) {
dev_err(dev, "%s - error sending open port command\n", __func__);
edge_port->openPending = false;
@@ -897,8 +895,7 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
/* now wait for the port to be completely opened */
wait_event_timeout(edge_port->wait_open, !edge_port->openPending,
OPEN_TIMEOUT);
-
- if (!edge_port->open) {
+ if (edge_port->openPending) {
/* open timed out */
dev_dbg(dev, "%s - open timeout\n", __func__);
edge_port->openPending = false;
@@ -926,6 +923,10 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
return -ENOMEM;
}
+ spin_lock_irq(&edge_port->ep_lock);
+ edge_port->open = true;
+ spin_unlock_irq(&edge_port->ep_lock);
+
dev_dbg(dev, "%s - Initialize TX fifo to %d bytes\n",
__func__, edge_port->maxTxCredits);
@@ -1818,7 +1819,6 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial,
/* we have completed the open */
edge_port->openPending = false;
- edge_port->open = true;
wake_up(&edge_port->wait_open);
return;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 04/12] USB: serial: io_edgeport: move initial termios update to open()
[not found] <20261023121530.186541-1-johan@kernel.org>
` (2 preceding siblings ...)
2026-10-23 12:15 ` [PATCH v2 03/12] USB: serial: io_edgeport: fix potential NULL-deref at open Johan Hovold
@ 2026-10-23 12:15 ` Johan Hovold
2026-10-23 12:15 ` [PATCH v2 05/12] USB: serial: io_edgeport: fix potential fifo corruption Johan Hovold
` (2 subsequent siblings)
6 siblings, 0 replies; 7+ messages in thread
From: Johan Hovold @ 2026-10-23 12:15 UTC (permalink / raw)
To: Johan Hovold; +Cc: linux-usb, linux-kernel, stable
Explicitly update the terminal settings on open() instead of doing so
from the interrupt completion handler when receiving an open command
response, which in theory can be received after a failed open attempt.
Note that this will be used to fix a FIFO corruption issue and also
allows for switching to synchronous commands.
Cc: stable@vger.kernel.org
Signed-off-by: Johan Hovold <johan@kernel.org>
---
drivers/usb/serial/io_edgeport.c | 64 +++++---------------------------
1 file changed, 10 insertions(+), 54 deletions(-)
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index e8e641e9a197..cdcff02c435b 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -281,8 +281,7 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData,
static int send_iosp_ext_cmd(struct edgeport_port *edge_port, __u8 command,
__u8 param);
static int calc_baud_rate_divisor(struct device *dev, int baud_rate, int *divisor);
-static void change_port_settings(struct tty_struct *tty,
- struct edgeport_port *edge_port,
+static void edge_set_termios(struct tty_struct *tty, struct usb_serial_port *port,
const struct ktermios *old_termios);
static int send_cmd_write_uart_register(struct edgeport_port *edge_port,
__u8 regNum, __u8 regValue);
@@ -923,6 +922,9 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
return -ENOMEM;
}
+ if (tty)
+ edge_set_termios(tty, port, NULL);
+
spin_lock_irq(&edge_port->ep_lock);
edge_port->open = true;
spin_unlock_irq(&edge_port->ep_lock);
@@ -1443,30 +1445,6 @@ static void edge_unthrottle(struct tty_struct *tty)
}
-/*****************************************************************************
- * SerialSetTermios
- * this function is called by the tty driver when it wants to change
- * the termios structure
- *****************************************************************************/
-static void edge_set_termios(struct tty_struct *tty,
- struct usb_serial_port *port,
- const struct ktermios *old_termios)
-{
- struct edgeport_port *edge_port = usb_get_serial_port_data(port);
-
- if (edge_port == NULL)
- return;
-
- if (!edge_port->open) {
- dev_dbg(&port->dev, "%s - port not opened\n", __func__);
- return;
- }
-
- /* change the port settings to the new ones specified */
- change_port_settings(tty, edge_port, old_termios);
-}
-
-
/*****************************************************************************
* get_lsr_info - get line status register info
*
@@ -1756,7 +1734,6 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial,
{
struct usb_serial_port *port;
struct edgeport_port *edge_port;
- struct tty_struct *tty;
struct device *dev;
__u8 code = edge_serial->rxStatusCode;
@@ -1808,15 +1785,6 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial,
__func__, edge_serial->rxPort, byte2, edge_port->txCredits);
handle_new_msr(edge_port, byte2);
- /* send the current line settings to the port so we are
- in sync with any further termios calls */
- tty = tty_port_tty_get(&edge_port->port->port);
- if (tty) {
- change_port_settings(tty,
- edge_port, &tty->termios);
- tty_kref_put(tty);
- }
-
/* we have completed the open */
edge_port->openPending = false;
wake_up(&edge_port->wait_open);
@@ -2328,18 +2296,12 @@ static int send_cmd_write_uart_register(struct edgeport_port *edge_port,
}
-/*****************************************************************************
- * change_port_settings
- * This routine is called to set the UART on the device to match the
- * specified new settings.
- *****************************************************************************/
-
-static void change_port_settings(struct tty_struct *tty,
- struct edgeport_port *edge_port, const struct ktermios *old_termios)
+static void edge_set_termios(struct tty_struct *tty, struct usb_serial_port *port,
+ const struct ktermios *old_termios)
{
- struct device *dev = &edge_port->port->dev;
- struct edgeport_serial *edge_serial =
- usb_get_serial_data(edge_port->port->serial);
+ struct edgeport_serial *edge_serial = usb_get_serial_data(port->serial);
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+ struct device *dev = &port->dev;
int baud;
unsigned cflag;
__u8 mask = 0xff;
@@ -2350,12 +2312,6 @@ static void change_port_settings(struct tty_struct *tty,
__u8 txFlow;
int status;
- if (!edge_port->open &&
- !edge_port->openPending) {
- dev_dbg(dev, "%s - port not opened\n", __func__);
- return;
- }
-
cflag = tty->termios.c_cflag;
switch (cflag & CSIZE) {
@@ -2489,7 +2445,7 @@ static void change_port_settings(struct tty_struct *tty,
dev_dbg(dev, "%s - baud rate = %d\n", __func__, baud);
status = send_cmd_write_baud_rate(edge_port, baud);
- if (status == -1) {
+ if (status == -1 && old_termios) {
/* Speed change was not possible - put back the old speed */
baud = tty_termios_baud_rate(old_termios);
tty_encode_baud_rate(tty, baud, baud);
--
2.55.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 05/12] USB: serial: io_edgeport: fix potential fifo corruption
[not found] <20261023121530.186541-1-johan@kernel.org>
` (3 preceding siblings ...)
2026-10-23 12:15 ` [PATCH v2 04/12] USB: serial: io_edgeport: move initial termios update to open() Johan Hovold
@ 2026-10-23 12:15 ` Johan Hovold
2026-10-23 12:15 ` [PATCH v2 06/12] USB: serial: io_edgeport: fix potential use-after-free on disconnect Johan Hovold
2026-10-23 12:15 ` [PATCH v2 07/12] USB: serial: io_edgeport: serialise MCR accesses Johan Hovold
6 siblings, 0 replies; 7+ messages in thread
From: Johan Hovold @ 2026-10-23 12:15 UTC (permalink / raw)
To: Johan Hovold; +Cc: linux-usb, linux-kernel, stable
The device buffer size is determined during open() and the driver
allocates a TX FIFO of corresponding size.
Add the missing sanity check to prevent memory corruption in case a
malicious device sends a second open response with a different buffer
size.
This issue was flagged by Sashiko when reviewing a related fix.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Link: https://sashiko.dev/#/patchset/20260714101316.823942-1-shpark061104%40gmail.com?part=1
Signed-off-by: Johan Hovold <johan@kernel.org>
---
drivers/usb/serial/io_edgeport.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index cdcff02c435b..b8fbcc8908d1 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -877,13 +877,17 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
}
/* initialize our port settings */
+ spin_lock_irq(&edge_port->ep_lock);
edge_port->txCredits = 0; /* Can't send any data yet */
+ edge_port->maxTxCredits = 0;
+ edge_port->openPending = true;
+ spin_unlock_irq(&edge_port->ep_lock);
+
/* Must always set this bit to enable ints! */
edge_port->shadowMCR = MCR_MASTER_IE;
edge_port->chaseResponsePending = false;
/* send a open port command */
- edge_port->openPending = true;
response = send_iosp_ext_cmd(edge_port, IOSP_CMD_OPEN_PORT, 0);
if (response < 0) {
dev_err(dev, "%s - error sending open port command\n", __func__);
@@ -1736,6 +1740,7 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial,
struct edgeport_port *edge_port;
struct device *dev;
__u8 code = edge_serial->rxStatusCode;
+ unsigned long flags;
/* switch the port pointer to the one being currently talked about */
if (edge_serial->rxPort >= edge_serial->serial->num_ports)
@@ -1779,6 +1784,12 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial,
}
if (code == IOSP_STATUS_OPEN_RSP) {
+ spin_lock_irqsave(&edge_port->ep_lock, flags);
+ /* reject stray open responses to avoid FIFO corruption */
+ if (!edge_port->openPending) {
+ spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+ return;
+ }
edge_port->txCredits = GET_TX_BUFFER_SIZE(byte3);
edge_port->maxTxCredits = edge_port->txCredits;
dev_dbg(dev, "%s - Port %u Open Response Initial MSR = %02x TxBufferSize = %d\n",
@@ -1787,6 +1798,8 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial,
/* we have completed the open */
edge_port->openPending = false;
+ spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+
wake_up(&edge_port->wait_open);
return;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 06/12] USB: serial: io_edgeport: fix potential use-after-free on disconnect
[not found] <20261023121530.186541-1-johan@kernel.org>
` (4 preceding siblings ...)
2026-10-23 12:15 ` [PATCH v2 05/12] USB: serial: io_edgeport: fix potential fifo corruption Johan Hovold
@ 2026-10-23 12:15 ` Johan Hovold
2026-10-23 12:15 ` [PATCH v2 07/12] USB: serial: io_edgeport: serialise MCR accesses Johan Hovold
6 siblings, 0 replies; 7+ messages in thread
From: Johan Hovold @ 2026-10-23 12:15 UTC (permalink / raw)
To: Johan Hovold; +Cc: linux-usb, linux-kernel, stable
The driver submits command URBs asynchronously but fails to stop them on
disconnect, something which could lead to a use-after-free when
accessing driver data in the completion handler after a port has been
unbound.
Add an URB anchor to track and kill outstanding command URBs on
disconnect.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Johan Hovold <johan@kernel.org>
---
drivers/usb/serial/io_edgeport.c | 19 ++++++-------------
1 file changed, 6 insertions(+), 13 deletions(-)
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index b8fbcc8908d1..0fe7495c47f4 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -225,6 +225,7 @@ struct edgeport_serial {
__u8 rxStatusParam; /* the receive status parameter */
__s16 rxBytesRemaining; /* the number of port bytes left to read */
struct usb_serial *serial; /* loop back to the owner of this object */
+ struct usb_anchor cmd_anchor;
};
/* baud rate information */
@@ -261,9 +262,6 @@ static const struct divisor_table_entry divisor_table[] = {
{ 230400, 1},
};
-/* Number of outstanding Command Write Urbs */
-static atomic_t CmdUrbs = ATOMIC_INIT(0);
-
/* function prototypes */
@@ -776,11 +774,6 @@ static void edge_bulk_out_cmd_callback(struct urb *urb)
struct device *dev = &urb->dev->dev;
int status = urb->status;
- atomic_dec(&CmdUrbs);
- dev_dbg(dev, "%s - FREE URB %p (outstanding %d)\n", __func__, urb,
- atomic_read(&CmdUrbs));
-
-
/* clean up the transfer buffer */
kfree(urb->transfer_buffer);
@@ -2127,24 +2120,21 @@ static int write_cmd_usb(struct edgeport_port *edge_port,
if (!urb)
return -ENOMEM;
- atomic_inc(&CmdUrbs);
- dev_dbg(dev, "%s - ALLOCATE URB %p (outstanding %d)\n",
- __func__, urb, atomic_read(&CmdUrbs));
-
usb_fill_bulk_urb(urb, edge_serial->serial->dev,
usb_sndbulkpipe(edge_serial->serial->dev,
edge_serial->bulk_out_endpoint),
buffer, length, edge_bulk_out_cmd_callback, edge_port);
edge_port->commandPending = true;
+ usb_anchor_urb(urb, &edge_serial->cmd_anchor);
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
/* something went wrong */
dev_err(dev, "%s - usb_submit_urb(write command) failed, status = %d\n",
__func__, status);
+ usb_unanchor_urb(urb);
usb_free_urb(urb);
- atomic_dec(&CmdUrbs);
return status;
}
@@ -2696,6 +2686,7 @@ static int edge_startup(struct usb_serial *serial)
spin_lock_init(&edge_serial->es_lock);
edge_serial->serial = serial;
+ init_usb_anchor(&edge_serial->cmd_anchor);
usb_set_serial_data(serial, edge_serial);
/* get the name for the device from the device */
@@ -2900,6 +2891,8 @@ static void edge_disconnect(struct usb_serial *serial)
{
struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
+ usb_kill_anchored_urbs(&edge_serial->cmd_anchor);
+
if (edge_serial->is_epic) {
usb_kill_urb(edge_serial->interrupt_read_urb);
usb_kill_urb(edge_serial->read_urb);
--
2.55.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 07/12] USB: serial: io_edgeport: serialise MCR accesses
[not found] <20261023121530.186541-1-johan@kernel.org>
` (5 preceding siblings ...)
2026-10-23 12:15 ` [PATCH v2 06/12] USB: serial: io_edgeport: fix potential use-after-free on disconnect Johan Hovold
@ 2026-10-23 12:15 ` Johan Hovold
6 siblings, 0 replies; 7+ messages in thread
From: Johan Hovold @ 2026-10-23 12:15 UTC (permalink / raw)
To: Johan Hovold; +Cc: linux-usb, linux-kernel, stable
Add a mutex to serialise modem control register updates to prevent
concurrent tasks from interfering with each other.
Note that the register updates are currently asynchronous so a task may
read back a value which has not yet taken effect.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Johan Hovold <johan@kernel.org>
---
drivers/usb/serial/io_edgeport.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 0fe7495c47f4..0fd68faa8427 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -168,6 +168,7 @@ struct edgeport_port {
struct urb *write_urb; /* write URB for this port */
bool write_in_progress; /* 'true' while a write URB is outstanding */
spinlock_t ep_lock;
+ struct mutex mutex;
__u8 shadowLCR; /* last LCR value received */
__u8 shadowMCR; /* last MCR value received */
@@ -877,7 +878,10 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
spin_unlock_irq(&edge_port->ep_lock);
/* Must always set this bit to enable ints! */
+ mutex_lock(&edge_port->mutex);
edge_port->shadowMCR = MCR_MASTER_IE;
+ mutex_unlock(&edge_port->mutex);
+
edge_port->chaseResponsePending = false;
/* send a open port command */
@@ -1398,9 +1402,11 @@ static void edge_throttle(struct tty_struct *tty)
/* if we are implementing RTS/CTS, toggle that line */
if (C_CRTSCTS(tty)) {
+ mutex_lock(&edge_port->mutex);
edge_port->shadowMCR &= ~MCR_RTS;
status = send_cmd_write_uart_register(edge_port, MCR,
edge_port->shadowMCR);
+ mutex_unlock(&edge_port->mutex);
if (status != 0)
return;
}
@@ -1435,9 +1441,11 @@ static void edge_unthrottle(struct tty_struct *tty)
}
/* if we are implementing RTS/CTS, toggle that line */
if (C_CRTSCTS(tty)) {
+ mutex_lock(&edge_port->mutex);
edge_port->shadowMCR |= MCR_RTS;
send_cmd_write_uart_register(edge_port, MCR,
edge_port->shadowMCR);
+ mutex_unlock(&edge_port->mutex);
}
}
@@ -1478,6 +1486,7 @@ static int edge_tiocmset(struct tty_struct *tty,
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned int mcr;
+ mutex_lock(&edge_port->mutex);
mcr = edge_port->shadowMCR;
if (set & TIOCM_RTS)
mcr |= MCR_RTS;
@@ -1496,6 +1505,7 @@ static int edge_tiocmset(struct tty_struct *tty,
edge_port->shadowMCR = mcr;
send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR);
+ mutex_unlock(&edge_port->mutex);
return 0;
}
@@ -1509,6 +1519,7 @@ static int edge_tiocmget(struct tty_struct *tty)
unsigned int mcr;
msr = edge_port->shadowMSR;
+ mutex_lock(&edge_port->mutex);
mcr = edge_port->shadowMCR;
result = ((mcr & MCR_DTR) ? TIOCM_DTR: 0) /* 0x002 */
| ((mcr & MCR_RTS) ? TIOCM_RTS: 0) /* 0x004 */
@@ -1516,6 +1527,7 @@ static int edge_tiocmget(struct tty_struct *tty)
| ((msr & EDGEPORT_MSR_CD) ? TIOCM_CAR: 0) /* 0x040 */
| ((msr & EDGEPORT_MSR_RI) ? TIOCM_RI: 0) /* 0x080 */
| ((msr & EDGEPORT_MSR_DSR) ? TIOCM_DSR: 0); /* 0x100 */
+ mutex_unlock(&edge_port->mutex);
return result;
}
@@ -2430,12 +2442,14 @@ static void edge_set_termios(struct tty_struct *tty, struct usb_serial_port *por
return;
/* set up the MCR register and send it to the EdgePort */
+ mutex_lock(&edge_port->mutex);
edge_port->shadowMCR = MCR_MASTER_IE;
if (cflag & CBAUD)
edge_port->shadowMCR |= (MCR_DTR | MCR_RTS);
status = send_cmd_write_uart_register(edge_port, MCR,
edge_port->shadowMCR);
+ mutex_unlock(&edge_port->mutex);
if (status != 0)
return;
@@ -2930,6 +2944,7 @@ static int edge_port_probe(struct usb_serial_port *port)
return -ENOMEM;
spin_lock_init(&edge_port->ep_lock);
+ mutex_init(&edge_port->mutex);
init_waitqueue_head(&edge_port->wait_open);
init_waitqueue_head(&edge_port->wait_chase);
--
2.55.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-10-23 12:16 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20261023121530.186541-1-johan@kernel.org>
2026-10-23 12:15 ` [PATCH v2 01/12] USB: serial: io_edgeport: fix NULL-deref on early status Johan Hovold
2026-10-23 12:15 ` [PATCH v2 02/12] USB: serial: io_edgeport: fix potential close() use-after-free Johan Hovold
2026-10-23 12:15 ` [PATCH v2 03/12] USB: serial: io_edgeport: fix potential NULL-deref at open Johan Hovold
2026-10-23 12:15 ` [PATCH v2 04/12] USB: serial: io_edgeport: move initial termios update to open() Johan Hovold
2026-10-23 12:15 ` [PATCH v2 05/12] USB: serial: io_edgeport: fix potential fifo corruption Johan Hovold
2026-10-23 12:15 ` [PATCH v2 06/12] USB: serial: io_edgeport: fix potential use-after-free on disconnect Johan Hovold
2026-10-23 12:15 ` [PATCH v2 07/12] USB: serial: io_edgeport: serialise MCR accesses Johan Hovold
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox