Re: [PATCH 1/2] serdev: fix race between tty-port unregister and in-flight callbacks
Markus Probst <[email protected]> Fri, 31 Jul 2026 11:30:53 +0000
| Newsgroups | org.kernel.vger.linux-serial,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
--=-EUFn1wPl5p1+FXr4nf96 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Fri, 2026-07-31 at 10:06 +0200, Greg Kroah-Hartman wrote: > From: Joshua Rogers <[email protected]> >=20 > serdev_tty_port_unregister() clears port->client_data and frees the > controller without synchronizing with in-flight flip buffer work. > This can cause NULL pointer dereferences or use-after-free if > ttyport_receive_buf() or ttyport_write_wakeup() runs concurrently. >=20 > Add cancel_work_sync() to drain pending buffer work before clearing > state, and add NULL checks for client_data in both callbacks as > secondary hardening. >=20 > Assisted-by: AISLE:Snapshot > Cc: stable <[email protected]> > Signed-off-by: Joshua Rogers <[email protected]> > Signed-off-by: Greg Kroah-Hartman <[email protected]> > --- > drivers/tty/serdev/serdev-ttyport.c | 15 +++++++++++++-- > 1 file changed, 13 insertions(+), 2 deletions(-) >=20 > diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/ser= dev-ttyport.c > index bab1b143b8a6..48ce5b3f8308 100644 > --- a/drivers/tty/serdev/serdev-ttyport.c > +++ b/drivers/tty/serdev/serdev-ttyport.c > @@ -26,9 +26,14 @@ static size_t ttyport_receive_buf(struct tty_port *por= t, const u8 *cp, > const u8 *fp, size_t count) > { > struct serdev_controller *ctrl =3D port->client_data; > - struct serport *serport =3D serdev_controller_get_drvdata(ctrl); > + struct serport *serport; > size_t ret; > =20 > + if (!ctrl) > + return 0; > + > + serport =3D serdev_controller_get_drvdata(ctrl); > + > if (!test_bit(SERPORT_ACTIVE, &serport->flags)) > return 0; > =20 > @@ -46,9 +51,14 @@ static size_t ttyport_receive_buf(struct tty_port *por= t, const u8 *cp, > static void ttyport_write_wakeup(struct tty_port *port) > { > struct serdev_controller *ctrl =3D port->client_data; > - struct serport *serport =3D serdev_controller_get_drvdata(ctrl); > + struct serport *serport; > struct tty_struct *tty; > =20 > + if (!ctrl) > + return; > + > + serport =3D serdev_controller_get_drvdata(ctrl); > + > tty =3D tty_port_tty_get(port); > if (!tty) > return; > @@ -312,6 +322,7 @@ int serdev_tty_port_unregister(struct tty_port *port) > return -ENODEV; > =20 > serdev_controller_remove(ctrl); > + cancel_work_sync(&port->buf.work); > port->client_data =3D NULL; > port->client_ops =3D &tty_port_default_client_ops; > serdev_controller_put(ctrl); So why exactly does tty keep calling `receive_buf` and `write_wakeup` with the tty port closed? After `serdev_controller_remove` is called, the tty port should already be closed by the drivers. Thanks - Markus Probst --=-EUFn1wPl5p1+FXr4nf96 Content-Type: application/pgp-signature; name="signature.asc" Content-Description: This is a digitally signed message part -----BEGIN PGP SIGNATURE----- iQJPBAABCAA5FiEEgnQYxPSsWOdyMMRzNHYf+OetQ9IFAmpsh1sbFIAAAAAABAAO bWFudTIsMi41KzEuMTIsMiwyAAoJEDR2H/jnrUPSCaAP/2GkIU4D5R4IBzj1A0NO YfYewKxajbkjyxRNQf1o+ccNdi5Ia6XE/JEIKo55rKQxkmRLI3w7q3AYrf2Lwg/V N111MjRH57BnPjzlUPxcmZ/atMhnHuyLCrfgnP+eesib6HarDVHXkX7HkcuseFGZ RwrZepRiUeSLYCzVSyz+BPevCVn9tgegwPQS7XMqo1ikeEdnU2NbLDjYkpwV96in h7O6OK4C/gfOpHmBsS0jUtWNZyf/fLZYMKmIsppjg++yADXgKfQs6KnNWrS9cTkp my4zIJdI7nwUbxN/SpZPF6EGs0uZV7BM7m8B72xyTJKCYvk4x9BkKdfyG34pefJU +/tv4DcpOv/ue99ONcO0dg+8rCed0N34kU/UW5ceuInkV7uZ+XlTpVDFqVptlYtJ a2xadVjX3wwBmulczlPqwUNx1HWCbHSsG8nksG+CPKfXX2GBzEa23G7HuNqEVp1N u0P/Y+6dh3xr2sSvsiz7N0NDKqRw8+FPDhVMeqi8Hebtw4C7JdHrY63HSUcjA1wV oE65t1fMlEUzSXuiurYU85XCJYT+phDtDwVOzv8rItQiK8f9c5mKvZ9XZc/pxPfX VcylFnH7NKV3IryvDlji7Ys4p4o+0GeM+Ryq5Npwn2nTCQd1sLLP2sJ/hXj+tx8L bM5DQWWaATJQ0QFFodb92s7p =ujKB -----END PGP SIGNATURE----- --=-EUFn1wPl5p1+FXr4nf96--