Bug 721 - mdev.conf subsystem match is wrong
Summary: mdev.conf subsystem match is wrong
Status: RESOLVED FIXED
Alias: None
Product: Busybox
Classification: Unclassified
Component: Other (show other bugs)
Version: unspecified
Hardware: PC Linux
: P5 normal
Target Milestone: ---
Assignee: unassigned
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-11-13 21:46 UTC by Michael Tokarev
Modified: 2010-04-03 23:52 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Tokarev 2009-11-13 21:46:46 UTC
In the code in util-linux/mdev.c, there's this fragment:

        /* Make path point to "subsystem/device_name" */
        if (path[5] == 'b') /* legacy /sys/block? */
                path += sizeof("/sys/") - 1;
        else
                path += sizeof("/sys/class/") - 1;

It assumes that the original path is starting either with "/sys/block" or "/sys/class".  But this is only true when traversing sysfs for `mdev -s', ie, "manually".  When mdev is called from /sbin/hotplug in response to actual kernel event, the path is like, for example, "/sys/devices/pci0000:00/0000:00:11.0/host0/target0:0:0/0:0:0:0/bsg/0:0:0:0" (actual example from my system).  Ie, it starts with something entirely different.

According to the kernel, the only reliable way to get subsystem name is to readlink("subsystem") in the device directory.  That did not exist in earlier kernels (but it's not a recent addition either).

Most of the time it's ok to assume that pre-last component of the path actually is the right thing, so it's ok to find pre-last slash on the pathname here.  It will work on all cases which I have examples for (ie, on all my systems).

So instead of the above, searching backwards for pre-last slash seems to be a good idea.  And ab-using 'path' variable is NOT a good idea, at least I don't think it is :)

Thanks!
Comment 1 Denys Vlasenko 2010-02-24 09:41:52 UTC
This was just applied to git:

        /* Make path point to "subsystem/device_name" */
-       if (path[5] == 'b') /* legacy /sys/block? */
+       subsystem_slash_devname = NULL;
+       /* Check for coldplug invocations first */
+       if (strncmp(path, "/sys/block/", 11) == 0) /* legacy case */
                path += sizeof("/sys/") - 1;
-       else
+       else if (strncmp(path, "/sys/class/", 11) == 0)
                path += sizeof("/sys/class/") - 1;
+       else {
+               /* Example of a hotplug invocation:
+                * SUBSYSTEM="block"
+                * DEVPATH="/sys" + "/devices/virtual/mtd/mtd3/mtdblock3"
+                * ("/sys" is added by mdev_main)
+                * - path does not contain subsystem
+                */
+               subsystem_slash_devname = concat_path_file(G.subsystem, device_name);
+               path = subsystem_slash_devname;
+       }

does it fix your case too?