Commit 8ce0bddd authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman Committed by Stefan Bader

tty: ldisc: add sysctl to prevent autoloading of ldiscs

BugLink: https://bugs.launchpad.net/bugs/1828420

commit 7c0cca7c 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: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: default avatarTheodore Ts'o <tytso@mit.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarKleber Sacilotto de Souza <kleber.souza@canonical.com>
Signed-off-by: default avatarStefan Bader <stefan.bader@canonical.com>
parent b22c20c8
...@@ -466,4 +466,27 @@ config MIPS_EJTAG_FDC_KGDB_CHAN ...@@ -466,4 +466,27 @@ config MIPS_EJTAG_FDC_KGDB_CHAN
help help
FDC channel number to use for KGDB. FDC channel number to use for KGDB.
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 endif # TTY
...@@ -513,6 +513,8 @@ void proc_clear_tty(struct task_struct *p) ...@@ -513,6 +513,8 @@ void proc_clear_tty(struct task_struct *p)
tty_kref_put(tty); tty_kref_put(tty);
} }
extern void tty_sysctl_init(void);
/** /**
* proc_set_tty - set the controlling terminal * proc_set_tty - set the controlling terminal
* *
...@@ -3724,6 +3726,7 @@ void console_sysfs_notify(void) ...@@ -3724,6 +3726,7 @@ void console_sysfs_notify(void)
*/ */
int __init tty_init(void) int __init tty_init(void)
{ {
tty_sysctl_init();
cdev_init(&tty_cdev, &tty_fops); cdev_init(&tty_cdev, &tty_fops);
if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) || if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0) register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
......
...@@ -148,6 +148,13 @@ static void put_ldops(struct tty_ldisc_ops *ldops) ...@@ -148,6 +148,13 @@ static void put_ldops(struct tty_ldisc_ops *ldops)
* takes tty_ldiscs_lock to guard against ldisc races * 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) static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc)
{ {
struct tty_ldisc *ld; struct tty_ldisc *ld;
...@@ -162,6 +169,8 @@ static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc) ...@@ -162,6 +169,8 @@ static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc)
*/ */
ldops = get_ldops(disc); ldops = get_ldops(disc);
if (IS_ERR(ldops)) { if (IS_ERR(ldops)) {
if (!capable(CAP_SYS_MODULE) && !tty_ldisc_autoload)
return ERR_PTR(-EPERM);
request_module("tty-ldisc-%d", disc); request_module("tty-ldisc-%d", disc);
ldops = get_ldops(disc); ldops = get_ldops(disc);
if (IS_ERR(ldops)) if (IS_ERR(ldops))
...@@ -835,3 +844,41 @@ void tty_ldisc_begin(void) ...@@ -835,3 +844,41 @@ void tty_ldisc_begin(void)
/* Setup the default TTY line discipline. */ /* Setup the default TTY line discipline. */
(void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY); (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
} }
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);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment