Skip to content

Commit aee5da7

Browse files
jhovoldgregkh
authored andcommitted
serdev: fix tty-port client deregistration
The port client data must be set when registering the serdev controller or client deregistration will fail (and the serdev devices are left registered and allocated) if the port was never opened in between. Make sure to clear the port client data on any probe errors to avoid a use-after-free when the client is later deregistered unconditionally (e.g. in a tty-port deregistration helper). Also move port client operation initialisation to registration. Note that the client ops must be restored on failed probe. Fixes: bed35c6 ("serdev: add a tty port controller driver") Signed-off-by: Johan Hovold <[email protected]> Reviewed-by: Rob Herring <[email protected]> Cc: stable <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent d3ba126 commit aee5da7

File tree

1 file changed

+10
-5
lines changed

1 file changed

+10
-5
lines changed

drivers/tty/serdev/serdev-ttyport.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,6 @@ static int ttyport_open(struct serdev_controller *ctrl)
102102
return PTR_ERR(tty);
103103
serport->tty = tty;
104104

105-
serport->port->client_ops = &client_ops;
106-
serport->port->client_data = ctrl;
107-
108105
if (tty->ops->open)
109106
tty->ops->open(serport->tty, NULL);
110107
else
@@ -215,6 +212,7 @@ struct device *serdev_tty_port_register(struct tty_port *port,
215212
struct device *parent,
216213
struct tty_driver *drv, int idx)
217214
{
215+
const struct tty_port_client_operations *old_ops;
218216
struct serdev_controller *ctrl;
219217
struct serport *serport;
220218
int ret;
@@ -233,15 +231,22 @@ struct device *serdev_tty_port_register(struct tty_port *port,
233231

234232
ctrl->ops = &ctrl_ops;
235233

234+
old_ops = port->client_ops;
235+
port->client_ops = &client_ops;
236+
port->client_data = ctrl;
237+
236238
ret = serdev_controller_add(ctrl);
237239
if (ret)
238-
goto err_controller_put;
240+
goto err_reset_data;
239241

240242
dev_info(&ctrl->dev, "tty port %s%d registered\n", drv->name, idx);
241243
return &ctrl->dev;
242244

243-
err_controller_put:
245+
err_reset_data:
246+
port->client_data = NULL;
247+
port->client_ops = old_ops;
244248
serdev_controller_put(ctrl);
249+
245250
return ERR_PTR(ret);
246251
}
247252

0 commit comments

Comments
 (0)