proc_tty_init called too late, crash possible

Andreas Schwab (schwab@issan.informatik.uni-dortmund.de)
Fri, 7 Mar 97 10:43:39 +0100


The proc file system is only initialized the first time it is mounted,
which is too late for proc_tty_register_driver to be able to register the
builtin drivers. Also it is possible that a tty driver module is unloaded
before /proc is ever mounted, in which case proc_tty_unregister_driver
would crash in proc_unregister. The following patch fixes both problems
by maintaining a list of entries for /proc/tty/driver that were registered
before proc_tty_init was called.

--- linux-2.1.28/fs/proc/proc_tty.c.~1~ Tue Mar 4 16:54:58 1997
+++ linux-2.1.28/fs/proc/proc_tty.c Thu Mar 6 15:39:25 1997
@@ -122,7 +122,13 @@
}

/*
- * Thsi function is called by register_tty_driver() to handle
+ * List of entries that were registered for /proc/tty/driver before
+ * proc_tty_init was called.
+ */
+static struct proc_dir_entry *deferred_tty_driver_entries;
+
+/*
+ * This function is called by register_tty_driver() to handle
* registering the driver's /proc handler into /proc/tty/driver/<foo>
*/
void proc_tty_register_driver(struct tty_driver *driver)
@@ -142,6 +148,11 @@
ent->data = driver;

driver->proc_entry = ent;
+
+ if (!proc_tty_driver) {
+ ent->next = deferred_tty_driver_entries;
+ deferred_tty_driver_entries = ent;
+ }
}

/*
@@ -155,7 +166,15 @@
if (!ent)
return;

- proc_unregister(proc_tty_driver, ent->low_ino);
+ if (!proc_tty_driver) {
+ struct proc_dir_entry **p;
+ for (p = &deferred_tty_driver_entries; *p; p = &(*p)->next)
+ if (*p == ent) {
+ *p = ent->next;
+ break;
+ }
+ } else
+ proc_unregister(proc_tty_driver, ent->low_ino);

driver->proc_entry = 0;
kfree(ent);
@@ -173,6 +192,11 @@
return;
proc_tty_ldisc = create_proc_entry("ldisc", S_IFDIR, proc_tty);
proc_tty_driver = create_proc_entry("driver", S_IFDIR, proc_tty);
+
+ while ((ent = deferred_tty_driver_entries) != NULL) {
+ deferred_tty_driver_entries = ent->next;
+ proc_register(proc_tty_driver, ent);
+ }

ent = create_proc_entry("ldiscs", 0, proc_tty);
ent->read_proc = tty_ldiscs_read_proc;

-- 
Andreas Schwab                                      "And now for something
schwab@issan.informatik.uni-dortmund.de              completely different"