[PATCH] tty: limit TCSBRKP break duration

From: Xincheng Wang

Date: Mon Jul 27 2026 - 01:56:07 EST


An RCU stall was observed while exercising tty ioctls on an
8250 Pericom PCI serial port.

The reproducer passed a very large argument to TCSBRKP. tty_ioctl()
multiplies the argument by 100 and forwards it to send_break(), whose
duration is an unsigned int. That can leave the serial break condition
asserted for an extremely long time and keep the IRQ line active on the
affected setup.

Clamp the duration before calling send_break() so normal values keep
their current behavior, while preventing excessively long break
intervals.

Signed-off-by: Xincheng Wang <22009200607@xxxxxxxxxxxxxxxxx>
---
drivers/tty/tty_io.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 6b283fd03..5872b2432 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -2454,6 +2454,21 @@ static int tiocgetd(struct tty_struct *tty, int __user *p)
return ret;
}

+#define TTY_BREAK_DEFAULT_MS 250
+#define TTY_TCSBRKP_UNIT_MS 100
+#define TTY_TCSBRKP_MAX_MS 5000
+
+static unsigned int tcsbrkp_duration(unsigned long arg)
+{
+ if (!arg)
+ return TTY_BREAK_DEFAULT_MS;
+
+ if (arg > TTY_TCSBRKP_MAX_MS / TTY_TCSBRKP_UNIT_MS)
+ return TTY_TCSBRKP_MAX_MS;
+
+ return arg * TTY_TCSBRKP_UNIT_MS;
+}
+
/**
* send_break - performed time break
* @tty: device to break on
@@ -2757,7 +2772,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return send_break(tty, 250);
return 0;
case TCSBRKP: /* support for POSIX tcsendbreak() */
- return send_break(tty, arg ? arg*100 : 250);
+ return send_break(tty, tcsbrkp_duration(arg));

case TIOCMGET:
return tty_tiocmget(tty, p);
--
2.34.1