Commit 0524513a authored by Jiri Slaby's avatar Jiri Slaby Committed by Greg Kroah-Hartman
Browse files

tty: don't store semi-state into tty drivers



When a tty driver pointer is used as a return value of struct
console's device() hook, don't store a semi-state into global variable
which holds the tty driver. It could mean console::device() would return
a bogus value. This is important esp. after the next patch where we
switch from alloc_tty_driver to tty_alloc_driver. tty_alloc_driver
returns ERR_PTR in case of error and that might have unexpected results
as the code doesn't expect this.

Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
Cc: Helge Deller <deller@gmx.de>
Cc: Chris Zankel <chris@zankel.net>
Cc: Max Filippov <jcmvbkbc@gmail.com>
Cc: Laurentiu Tudor <laurentiu.tudor@nxp.com>
Cc: Felipe Balbi <balbi@kernel.org>
Reviewed-by: default avatarMax Filippov <jcmvbkbc@gmail.com>
Acked-by: Helge Deller <deller@gmx.de>	# parisc
Signed-off-by: default avatarJiri Slaby <jslaby@suse.cz>
Link: https://lore.kernel.org/r/20210723074317.32690-4-jslaby@suse.cz


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 7ccbdcc4
Loading
Loading
Loading
Loading
+15 −12
Original line number Diff line number Diff line
@@ -120,35 +120,38 @@ early_param("debug", nf_debug_setup);

static int __init nfcon_init(void)
{
	struct tty_driver *driver;
	int res;

	stderr_id = nf_get_id("NF_STDERR");
	if (!stderr_id)
		return -ENODEV;

	nfcon_tty_driver = alloc_tty_driver(1);
	if (!nfcon_tty_driver)
	driver = alloc_tty_driver(1);
	if (!driver)
		return -ENOMEM;

	tty_port_init(&nfcon_tty_port);

	nfcon_tty_driver->driver_name = "nfcon";
	nfcon_tty_driver->name = "nfcon";
	nfcon_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM;
	nfcon_tty_driver->subtype = SYSTEM_TYPE_TTY;
	nfcon_tty_driver->init_termios = tty_std_termios;
	nfcon_tty_driver->flags = TTY_DRIVER_REAL_RAW;
	driver->driver_name = "nfcon";
	driver->name = "nfcon";
	driver->type = TTY_DRIVER_TYPE_SYSTEM;
	driver->subtype = SYSTEM_TYPE_TTY;
	driver->init_termios = tty_std_termios;
	driver->flags = TTY_DRIVER_REAL_RAW;

	tty_set_operations(nfcon_tty_driver, &nfcon_tty_ops);
	tty_port_link_device(&nfcon_tty_port, nfcon_tty_driver, 0);
	res = tty_register_driver(nfcon_tty_driver);
	tty_set_operations(driver, &nfcon_tty_ops);
	tty_port_link_device(&nfcon_tty_port, driver, 0);
	res = tty_register_driver(driver);
	if (res) {
		pr_err("failed to register nfcon tty driver\n");
		put_tty_driver(nfcon_tty_driver);
		put_tty_driver(driver);
		tty_port_destroy(&nfcon_tty_port);
		return res;
	}

	nfcon_tty_driver = driver;

	if (!(nf_console.flags & CON_ENABLED))
		register_console(&nf_console);

+15 −13
Original line number Diff line number Diff line
@@ -138,6 +138,7 @@ static struct tty_driver *pdc_console_tty_driver;

static int __init pdc_console_tty_driver_init(void)
{
	struct tty_driver *driver;
	int err;

	/* Check if the console driver is still registered.
@@ -160,31 +161,32 @@ static int __init pdc_console_tty_driver_init(void)
	printk(KERN_INFO "The PDC console driver is still registered, removing CON_BOOT flag\n");
	pdc_cons.flags &= ~CON_BOOT;

	pdc_console_tty_driver = alloc_tty_driver(1);

	if (!pdc_console_tty_driver)
	driver = alloc_tty_driver(1);
	if (!driver)
		return -ENOMEM;

	tty_port_init(&tty_port);

	pdc_console_tty_driver->driver_name = "pdc_cons";
	pdc_console_tty_driver->name = "ttyB";
	pdc_console_tty_driver->major = MUX_MAJOR;
	pdc_console_tty_driver->minor_start = 0;
	pdc_console_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM;
	pdc_console_tty_driver->init_termios = tty_std_termios;
	pdc_console_tty_driver->flags = TTY_DRIVER_REAL_RAW |
	driver->driver_name = "pdc_cons";
	driver->name = "ttyB";
	driver->major = MUX_MAJOR;
	driver->minor_start = 0;
	driver->type = TTY_DRIVER_TYPE_SYSTEM;
	driver->init_termios = tty_std_termios;
	driver->flags = TTY_DRIVER_REAL_RAW |
		TTY_DRIVER_RESET_TERMIOS;
	tty_set_operations(pdc_console_tty_driver, &pdc_console_tty_ops);
	tty_port_link_device(&tty_port, pdc_console_tty_driver, 0);
	tty_set_operations(driver, &pdc_console_tty_ops);
	tty_port_link_device(&tty_port, driver, 0);

	err = tty_register_driver(pdc_console_tty_driver);
	err = tty_register_driver(driver);
	if (err) {
		printk(KERN_ERR "Unable to register the PDC console TTY driver\n");
		tty_port_destroy(&tty_port);
		return err;
	}

	pdc_console_tty_driver = driver;

	return 0;
}
device_initcall(pdc_console_tty_driver_init);
+18 −15
Original line number Diff line number Diff line
@@ -136,39 +136,42 @@ static const struct tty_operations serial_ops = {

static int __init rs_init(void)
{
	struct tty_driver *driver;
	int ret;

	serial_driver = alloc_tty_driver(SERIAL_MAX_NUM_LINES);
	if (!serial_driver)
	driver = alloc_tty_driver(SERIAL_MAX_NUM_LINES);
	if (!driver)
		return -ENOMEM;

	tty_port_init(&serial_port);

	/* Initialize the tty_driver structure */

	serial_driver->driver_name = "iss_serial";
	serial_driver->name = "ttyS";
	serial_driver->major = TTY_MAJOR;
	serial_driver->minor_start = 64;
	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
	serial_driver->subtype = SERIAL_TYPE_NORMAL;
	serial_driver->init_termios = tty_std_termios;
	serial_driver->init_termios.c_cflag =
	driver->driver_name = "iss_serial";
	driver->name = "ttyS";
	driver->major = TTY_MAJOR;
	driver->minor_start = 64;
	driver->type = TTY_DRIVER_TYPE_SERIAL;
	driver->subtype = SERIAL_TYPE_NORMAL;
	driver->init_termios = tty_std_termios;
	driver->init_termios.c_cflag =
		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
	serial_driver->flags = TTY_DRIVER_REAL_RAW;
	driver->flags = TTY_DRIVER_REAL_RAW;

	tty_set_operations(serial_driver, &serial_ops);
	tty_port_link_device(&serial_port, serial_driver, 0);
	tty_set_operations(driver, &serial_ops);
	tty_port_link_device(&serial_port, driver, 0);

	ret = tty_register_driver(serial_driver);
	ret = tty_register_driver(driver);
	if (ret) {
		pr_err("Couldn't register serial driver\n");
		tty_driver_kref_put(serial_driver);
		tty_driver_kref_put(driver);
		tty_port_destroy(&serial_port);

		return ret;
	}

	serial_driver = driver;

	return 0;
}

+19 −16
Original line number Diff line number Diff line
@@ -1490,34 +1490,35 @@ static const struct tty_port_operations amiga_port_ops = {
static int __init amiga_serial_probe(struct platform_device *pdev)
{
	struct serial_state *state = &serial_state;
	struct tty_driver *driver;
	unsigned long flags;
	int error;

	serial_driver = alloc_tty_driver(1);
	if (!serial_driver)
	driver = alloc_tty_driver(1);
	if (!driver)
		return -ENOMEM;

	/* Initialize the tty_driver structure */

	serial_driver->driver_name = "amiserial";
	serial_driver->name = "ttyS";
	serial_driver->major = TTY_MAJOR;
	serial_driver->minor_start = 64;
	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
	serial_driver->subtype = SERIAL_TYPE_NORMAL;
	serial_driver->init_termios = tty_std_termios;
	serial_driver->init_termios.c_cflag =
	driver->driver_name = "amiserial";
	driver->name = "ttyS";
	driver->major = TTY_MAJOR;
	driver->minor_start = 64;
	driver->type = TTY_DRIVER_TYPE_SERIAL;
	driver->subtype = SERIAL_TYPE_NORMAL;
	driver->init_termios = tty_std_termios;
	driver->init_termios.c_cflag =
		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
	serial_driver->flags = TTY_DRIVER_REAL_RAW;
	tty_set_operations(serial_driver, &serial_ops);
	driver->flags = TTY_DRIVER_REAL_RAW;
	tty_set_operations(driver, &serial_ops);

	memset(state, 0, sizeof(*state));
	state->port = (int)&amiga_custom.serdatr; /* Just to give it a value */
	tty_port_init(&state->tport);
	state->tport.ops = &amiga_port_ops;
	tty_port_link_device(&state->tport, serial_driver, 0);
	tty_port_link_device(&state->tport, driver, 0);

	error = tty_register_driver(serial_driver);
	error = tty_register_driver(driver);
	if (error)
		goto fail_put_tty_driver;

@@ -1558,15 +1559,17 @@ static int __init amiga_serial_probe(struct platform_device *pdev)

	platform_set_drvdata(pdev, state);

	serial_driver = driver;

	return 0;

fail_free_irq:
	free_irq(IRQ_AMIGA_TBE, state);
fail_unregister:
	tty_unregister_driver(serial_driver);
	tty_unregister_driver(driver);
fail_put_tty_driver:
	tty_port_destroy(&state->tport);
	put_tty_driver(serial_driver);
	put_tty_driver(driver);
	return error;
}

+16 −12
Original line number Diff line number Diff line
@@ -751,6 +751,7 @@ static struct platform_driver ehv_bc_tty_driver = {
 */
static int __init ehv_bc_init(void)
{
	struct tty_driver *driver;
	struct device_node *np;
	unsigned int count = 0; /* Number of elements in bcs[] */
	int ret;
@@ -773,26 +774,28 @@ static int __init ehv_bc_init(void)
	if (!bcs)
		return -ENOMEM;

	ehv_bc_driver = alloc_tty_driver(count);
	if (!ehv_bc_driver) {
	driver = alloc_tty_driver(count);
	if (!driver) {
		ret = -ENOMEM;
		goto err_free_bcs;
	}

	ehv_bc_driver->driver_name = "ehv-bc";
	ehv_bc_driver->name = ehv_bc_console.name;
	ehv_bc_driver->type = TTY_DRIVER_TYPE_CONSOLE;
	ehv_bc_driver->subtype = SYSTEM_TYPE_CONSOLE;
	ehv_bc_driver->init_termios = tty_std_termios;
	ehv_bc_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
	tty_set_operations(ehv_bc_driver, &ehv_bc_ops);
	driver->driver_name = "ehv-bc";
	driver->name = ehv_bc_console.name;
	driver->type = TTY_DRIVER_TYPE_CONSOLE;
	driver->subtype = SYSTEM_TYPE_CONSOLE;
	driver->init_termios = tty_std_termios;
	driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
	tty_set_operations(driver, &ehv_bc_ops);

	ret = tty_register_driver(ehv_bc_driver);
	ret = tty_register_driver(driver);
	if (ret) {
		pr_err("ehv-bc: could not register tty driver (ret=%i)\n", ret);
		goto err_put_tty_driver;
	}

	ehv_bc_driver = driver;

	ret = platform_driver_register(&ehv_bc_tty_driver);
	if (ret) {
		pr_err("ehv-bc: could not register platform driver (ret=%i)\n",
@@ -803,9 +806,10 @@ static int __init ehv_bc_init(void)
	return 0;

err_deregister_tty_driver:
	tty_unregister_driver(ehv_bc_driver);
	ehv_bc_driver = NULL;
	tty_unregister_driver(driver);
err_put_tty_driver:
	put_tty_driver(ehv_bc_driver);
	put_tty_driver(driver);
err_free_bcs:
	kfree(bcs);

Loading