| From 7c0cca7c847e6e019d67b7d793efbbe3b947d004 Mon Sep 17 00:00:00 2001 |
| From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Date: Mon, 21 Jan 2019 17:26:42 +0100 |
| Subject: tty: ldisc: add sysctl to prevent autoloading of ldiscs |
| |
| From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| commit 7c0cca7c847e6e019d67b7d793efbbe3b947d004 upstream. |
| |
| By default, the kernel will automatically load the module of any line |
| dicipline that is asked for. As this sometimes isn't the safest thing |
| to do, provide a sysctl to disable this feature. |
| |
| By default, we set this to 'y' as that is the historical way that Linux |
| has worked, and we do not want to break working systems. But in the |
| future, perhaps this can default to 'n' to prevent this functionality. |
| |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Reviewed-by: Theodore Ts'o <tytso@mit.edu> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/tty/Kconfig | 24 ++++++++++++++++++++++++ |
| drivers/tty/tty_io.c | 3 +++ |
| drivers/tty/tty_ldisc.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ |
| 3 files changed, 74 insertions(+) |
| |
| --- a/drivers/tty/Kconfig |
| +++ b/drivers/tty/Kconfig |
| @@ -441,4 +441,28 @@ config VCC |
| depends on SUN_LDOMS |
| help |
| Support for Sun logical domain consoles. |
| + |
| +config LDISC_AUTOLOAD |
| + bool "Automatically load TTY Line Disciplines" |
| + default y |
| + help |
| + Historically the kernel has always automatically loaded any |
| + line discipline that is in a kernel module when a user asks |
| + for it to be loaded with the TIOCSETD ioctl, or through other |
| + means. This is not always the best thing to do on systems |
| + where you know you will not be using some of the more |
| + "ancient" line disciplines, so prevent the kernel from doing |
| + this unless the request is coming from a process with the |
| + CAP_SYS_MODULE permissions. |
| + |
| + Say 'Y' here if you trust your userspace users to do the right |
| + thing, or if you have only provided the line disciplines that |
| + you know you will be using, or if you wish to continue to use |
| + the traditional method of on-demand loading of these modules |
| + by any user. |
| + |
| + This functionality can be changed at runtime with the |
| + dev.tty.ldisc_autoload sysctl, this configuration option will |
| + only set the default value of this functionality. |
| + |
| endif # TTY |
| --- a/drivers/tty/tty_io.c |
| +++ b/drivers/tty/tty_io.c |
| @@ -513,6 +513,8 @@ static const struct file_operations hung |
| static DEFINE_SPINLOCK(redirect_lock); |
| static struct file *redirect; |
| |
| +extern void tty_sysctl_init(void); |
| + |
| /** |
| * tty_wakeup - request more data |
| * @tty: terminal |
| @@ -3483,6 +3485,7 @@ void console_sysfs_notify(void) |
| */ |
| int __init tty_init(void) |
| { |
| + tty_sysctl_init(); |
| cdev_init(&tty_cdev, &tty_fops); |
| if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) || |
| register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0) |
| --- a/drivers/tty/tty_ldisc.c |
| +++ b/drivers/tty/tty_ldisc.c |
| @@ -156,6 +156,13 @@ static void put_ldops(struct tty_ldisc_o |
| * takes tty_ldiscs_lock to guard against ldisc races |
| */ |
| |
| +#if defined(CONFIG_LDISC_AUTOLOAD) |
| + #define INITIAL_AUTOLOAD_STATE 1 |
| +#else |
| + #define INITIAL_AUTOLOAD_STATE 0 |
| +#endif |
| +static int tty_ldisc_autoload = INITIAL_AUTOLOAD_STATE; |
| + |
| static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc) |
| { |
| struct tty_ldisc *ld; |
| @@ -170,6 +177,8 @@ static struct tty_ldisc *tty_ldisc_get(s |
| */ |
| ldops = get_ldops(disc); |
| if (IS_ERR(ldops)) { |
| + if (!capable(CAP_SYS_MODULE) && !tty_ldisc_autoload) |
| + return ERR_PTR(-EPERM); |
| request_module("tty-ldisc-%d", disc); |
| ldops = get_ldops(disc); |
| if (IS_ERR(ldops)) |
| @@ -845,3 +854,41 @@ void tty_ldisc_deinit(struct tty_struct |
| tty_ldisc_put(tty->ldisc); |
| tty->ldisc = NULL; |
| } |
| + |
| +static int zero; |
| +static int one = 1; |
| +static struct ctl_table tty_table[] = { |
| + { |
| + .procname = "ldisc_autoload", |
| + .data = &tty_ldisc_autoload, |
| + .maxlen = sizeof(tty_ldisc_autoload), |
| + .mode = 0644, |
| + .proc_handler = proc_dointvec, |
| + .extra1 = &zero, |
| + .extra2 = &one, |
| + }, |
| + { } |
| +}; |
| + |
| +static struct ctl_table tty_dir_table[] = { |
| + { |
| + .procname = "tty", |
| + .mode = 0555, |
| + .child = tty_table, |
| + }, |
| + { } |
| +}; |
| + |
| +static struct ctl_table tty_root_table[] = { |
| + { |
| + .procname = "dev", |
| + .mode = 0555, |
| + .child = tty_dir_table, |
| + }, |
| + { } |
| +}; |
| + |
| +void tty_sysctl_init(void) |
| +{ |
| + register_sysctl_table(tty_root_table); |
| +} |