Fix for strange name module loading requests

Regis Duchesne (regis@via.ecp.fr)
Wed, 28 Jan 1998 05:05:01 +0100 (CET)


> Looks like you're close to tracking it down -- why don't you put some
> printks in the kernel code for kerneld requests. When you find a bad
> name coming through, force an oops to get a stack backtrace, and see
> what code is passing the invalid names.
I'm pretty new to kernel debugging, thanks for the idea (even if it
goes without saying, it always goes better when it is said :)

Stupid question from beginners like me :
"How to force an oops in kernel code?"
Answer for the record : just try to write something at address 0.

Anyway, with Bill's valuable advice, I tracked down that bug : the
2.1.79 patch (net/ipv4/af_inet.c) allowed the device to handle every ioctl
call that the INET socket can not handle itself. This revealed a weakness
of dev_ioctl(), which does not look at the ioctl _before_ assuming that
it can handle it, and it can load the adequate device module.

Here is the fix (against 2.1.82) for these horrible things :
Jan 27 10:30:43 Celine modprobe: can't locate module X!^O@^X-
Jan 27 10:30:43 Celine modprobe: can't locate module ^D

--- linux/net/core/dev.c.orig Tue Jan 27 18:45:46 1998
+++ linux/net/core/dev.c Wed Jan 28 04:24:03 1998
@@ -49,6 +49,7 @@
* Thomas Bogendoerfer : Return ENODEV for dev_open, if there
* is no device open function.
* Andi Kleen : Fix error reporting for SIOCGIFCONF
+ * Régis Duchesne : Fix the argument check in dev_ioctl()
*
*/

@@ -1534,7 +1535,6 @@
return -EINVAL;
}

-
/*
* This function handles all "interface"-type I/O control requests. The actual
* 'doing' part of this is dev_ifsioc above.
@@ -1566,25 +1566,19 @@
return dev_ifname((struct ifreq *)arg);
}

+ /*
+ * Fetch the interface name from the info block.
+ */
+
if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
return -EFAULT;
-
ifr.ifr_name[IFNAMSIZ-1] = 0;
-
#ifdef CONFIG_NET_ALIAS
colon = strchr(ifr.ifr_name, ':');
if (colon)
*colon = 0;
#endif

- /*
- * See which interface the caller is talking about.
- */
-
-#ifdef CONFIG_KERNELD
- dev_load(ifr.ifr_name);
-#endif
-
switch(cmd)
{
/*
@@ -1602,6 +1596,9 @@
case SIOCGIFMAP:
case SIOCGIFINDEX:
case SIOCGIFTXQLEN:
+#ifdef CONFIG_KERNELD
+ dev_load(ifr.ifr_name);
+#endif
ret = dev_ifsioc(&ifr, cmd);
if (!ret) {
#ifdef CONFIG_NET_ALIAS
@@ -1632,6 +1629,9 @@
case SIOCSIFTXQLEN:
if (!suser())
return -EPERM;
+#ifdef CONFIG_KERNELD
+ dev_load(ifr.ifr_name);
+#endif
rtnl_lock();
ret = dev_ifsioc(&ifr, cmd);
rtnl_unlock();
@@ -1652,6 +1652,9 @@
default:
if (cmd >= SIOCDEVPRIVATE &&
cmd <= SIOCDEVPRIVATE + 15) {
+#ifdef CONFIG_KERNELD
+ dev_load(ifr.ifr_name);
+#endif
rtnl_lock();
ret = dev_ifsioc(&ifr, cmd);
rtnl_unlock();
@@ -1664,8 +1667,15 @@
if (IW_IS_SET(cmd)) {
if (!suser())
return -EPERM;
+#ifdef CONFIG_KERNELD
+ dev_load(ifr.ifr_name);
+#endif
rtnl_lock();
}
+#ifdef CONFIG_KERNELD
+ else
+ dev_load(ifr.ifr_name);
+#endif
ret = dev_ifsioc(&ifr, cmd);
if (IW_IS_SET(cmd))
rtnl_unlock();

Regards,

Regis "HPReg" Duchesne - Engineering Student at ***** ******** *****
www http://www.via.ecp.fr/~regis/
(O o) I use Linux & 3Com (1135 KB/s over 10Mb/s ethernet)
--.oOO--(_)--OOo.-----------------------------------------------------------