|
|
@@ -156,6 +156,13 @@ static void put_ldops(struct tty_ldisc_ops *ldops)
|
|
|
* 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(struct tty_struct *tty, int disc)
|
|
|
*/
|
|
|
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))
|
|
|
@@ -829,3 +838,41 @@ void tty_ldisc_deinit(struct tty_struct *tty)
|
|
|
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);
|
|
|
+}
|