Bug 591

Summary: modprobe-small: incorrect alias detection
Product: Busybox Reporter: Jiri J. <jirij.jabb>
Component: OtherAssignee: unassigned
Status: RESOLVED FIXED    
Severity: normal CC: busybox-cvs
Priority: P3    
Version: unspecified   
Target Milestone: ---   
Hardware: PC   
OS: Linux   
Host: Target:
Build:
Attachments: patch: first version with two additional malloc calls
snd_intel8x0 module load+unload, with deps

Description Jiri J. 2009-09-03 14:25:12 UTC
Simplified modprobe tries to detect aliases from module "bodies". While this works fine under the most obvious cases, it doesn't work on all module aliases for a specific reason.


I've turned on the debugging macros in modprobe-small.c and tried to load up an atiixp.ko module by it's alias:

/ # grep 'alias=' /lib/modules/2.6.26-2-686/kernel/drivers/ide/pci/atiixp.ko
alias=pci:v00001002d0000439Csv*sd*bc*sc*i*
alias=pci:v00001002d0000438Csv*sd*bc*sc*i*
alias=pci:v00001002d00004376sv*sd*bc*sc*i*
alias=pci:v00001002d00004369sv*sd*bc*sc*i*
alias=pci:v00001002d00004349sv*sd*bc*sc*i*

/ # modprobe pci:v00001002d0000439Csv*sd*bc*sc*i*
modprobe: loading modules.dep.bb
modprobe: process_module('pci:v00001002d0000439Csv*sd*bc*sc*i*','(null)')
modprobe: already_loaded:0 is_rmmod:0
modprobe: process_module('pci:v00001002d0000439Csv*sd*bc*sc*i*'): options:'(null)'
modprobe: find_alias('pci:v00001002d0000439Csv*sd*bc*sc*i*')
modprobe: found alias 'pci:v00001002d0000439Csv*sd*bc*sc*i*' in module 'kernel/drivers/ide/pci/atiixp.ko'
modprobe: recurse on dep 'ide_core'
modprobe: process_module('ide_core','(null)')
modprobe: already_loaded:1 is_rmmod:0
modprobe: nothing to do for 'ide_core'
modprobe: recurse on dep 'ide_core' done
modprobe: load_module('kernel/drivers/ide/pci/atiixp.ko','(null)')
modprobe: load_module:0

.. which worked.
When I, however, try to load ide-disk, m-disk or any similar module alias, it fails:

/ # grep 'alias=' /lib/modules/2.6.26-2-686/kernel/drivers/ide/ide-tape.ko
alias=char-major-37-*
alias=ide:*m-tape*

/ # modprobe ide:m-tape
modprobe: loading modules.dep.bb
modprobe: process_module('ide:m-tape','(null)')
modprobe: already_loaded:0 is_rmmod:0
modprobe: process_module('ide:m_tape'): options:'(null)'
modprobe: find_alias('ide:m_tape')
modprobe: find_alias 'ide:m_tape' returns (nil)
modprobe: module 'ide:m_tape' not found


The problem is in the module name processing, which is done before an actual alias check. Ie. replace(name, '-', '_') is called before the alias detection code. Commenting the replace call made this particular case work:

/ # modprobe ide:m-tape
modprobe: loading modules.dep.bb
modprobe: process_module('ide:m-tape','(null)')
modprobe: already_loaded:0 is_rmmod:0
modprobe: process_module('ide:m-tape'): options:'(null)'
modprobe: find_alias('ide:m-tape')
modprobe: found alias 'ide:m-tape' in module 'kernel/drivers/ide/ide-tape.ko'
modprobe: recurse on dep 'ide_core'
modprobe: process_module('ide_core','(null)')
modprobe: already_loaded:1 is_rmmod:0
modprobe: nothing to do for 'ide_core'
modprobe: recurse on dep 'ide_core' done
modprobe: load_module('kernel/drivers/ide/ide-tape.ko','(null)')
modprobe: load_module:0

The correct solution, however, would be to move the replace function call or somewhat (and more likely) restructuralize the code itself.

Tested on 44f174e (2009-08-31) with CONFIG_MODPROBE_SMALL enabled.

Thanks.
Comment 1 Jiri J. 2009-09-03 17:09:30 UTC
Oh, I see I didn't explicitly mentioned the relation to dependencies.

        /* "dependency1 depandency2" */
        reset_stringbuf();
        ptr = find_keyword(module_image, len, "depends=");
        if (ptr && *ptr) {
                replace(ptr, ',', ' ');
                replace(ptr, '-', '_');
                dbg2_error_msg("dep:'%s'", ptr);
                append(ptr);
        }

modprobe: nothing to do for 'ide_core'
modprobe: recurse on dep 'ide_core' done

Obviously, it should be ide-core.
Comment 2 Jiri J. 2009-09-03 17:23:20 UTC
Again, I have to correct myself (sorry for that, may it be the last time); the replacement of '-' for '_' should be of course there (which is the ide_core case), but the original '-' should be, in my opinion (before I correct myself again, aargh), kept for alias lookup.
Comment 3 Jiri J. 2009-09-06 18:58:16 UTC
Created attachment 639 [details]
patch: first version with two additional malloc calls

After reading through the file a bit, I made this patch. Tested under various circumstances - for example usage with mdev as hotplug - upon triggering the pci device "add" uevent, it loads the piix module, which triggers another hotplug event, mdev reads "ide:m-disk" and "ide:m-cdrom" modaliases, passes them one-by-one to modprobe (using mdev.conf entry), ide-gd_mod gets loaded (along with ide-cd_mod) and /dev/hd[ac] device files are created.

You may notice there are two new allocation calls (xstrdup), which isn't so nice, but I found this solution to be the cleanest. If it's really that problematic, it should be possible to add new config entry - something like "use strict module names", ie. omit the ide-gd_mod/ide_gd-mod/ide_gd_mod/ide-gd-mod modutils-like "check" and strictly use module filename (which frees us of the "TODO" there and spares 2 malloc() calls).
Comment 4 Denys Vlasenko 2009-09-07 00:34:57 UTC
Thanks for diagnosing it!

How about this, much smaller change?

--- busybox.2/modutils/modprobe-small.c 2009-09-06 12:43:28.000000000 +0200
+++ busybox.3/modutils/modprobe-small.c 2009-09-07 02:34:59.000000000 +0200
@@ -218,6 +218,7 @@ static void parse_module(module_info *in
        bksp(); /* remove last ' ' */
        appendc('\0');
        info->aliases = copy_stringbuf();
+       replace(info->aliases, '-', '_');
 
        /* "dependency1 depandency2" */
        reset_stringbuf();


It seems to work for me. Please let me know if it doesn't work for you.
Provide the debug log.
Comment 5 Jiri J. 2009-09-07 13:57:23 UTC
Created attachment 641 [details]
snd_intel8x0 module load+unload, with deps

(In reply to comment #4)
> Thanks for diagnosing it!
> 
> How about this, much smaller change?
> 
> --- busybox.2/modutils/modprobe-small.c 2009-09-06 12:43:28.000000000 +0200
> +++ busybox.3/modutils/modprobe-small.c 2009-09-07 02:34:59.000000000 +0200
> @@ -218,6 +218,7 @@ static void parse_module(module_info *in
>         bksp(); /* remove last ' ' */
>         appendc('\0');
>         info->aliases = copy_stringbuf();
> +       replace(info->aliases, '-', '_');
> 
>         /* "dependency1 depandency2" */
>         reset_stringbuf();
> 
> 
> It seems to work for me. Please let me know if it doesn't work for you.
> Provide the debug log.
> 

All I can say is that it works for me. Debug logs attached, I'm sorry I couldn't copy&paste the QEMU output, but it's not that easy in initramfs, so instead I made another test on my primary desktop, it shows very similar output:

/ # modprobe ide:m-tape
modprobe: loading modules.dep.bb
modprobe: process_module('ide:m-tape','(null)')
modprobe: already_loaded:0 is_rmmod:0
modprobe: process_module('ide:m_tape'): options:'(null)'
modprobe: find_alias('ide:m_tape')
modprobe: found alias 'ide:m_tape' in module 'kernel/drivers/ide/ide-tape.ko'
modprobe: recurse on dep 'ide_core'
modprobe: process_module('ide_core','(null)')
modprobe: already_loaded:1 is_rmmod:0
modprobe: nothing to do for 'ide_core'
modprobe: recurse on dep 'ide_core' done
modprobe: load_module('kernel/drivers/ide/ide-tape.ko','(null)')
modprobe: load_module:0

/ # lsmod |grep tape
ide_tape 21424 0 - Live 0xf096e000
ide_core 96136 6 ide_tape,atiixp,ide_cd_mod,ide_disk,piix,ide_pci_generic, Live 0xf0884000

/ # rmmod ide_tape
rmmod: loading modules.dep.bb
rmmod: process_module('ide_tape','(null)')
rmmod: already_loaded:1 is_rmmod:1
rmmod: find_alias('ide_tape')
rmmod: found 'ide_tape' in module 'kernel/drivers/ide/ide-tape.ko'
rmmod: recurse on dep 'ide_core'
rmmod: process_module('ide_core','(null)')
rmmod: already_loaded:1 is_rmmod:1
rmmod: find_alias('ide_core')
rmmod: found 'ide_core' in module 'kernel/drivers/ide/ide-core.ko'
rmmod: remove 'ide_core': Resource temporarily unavailable
rmmod: recurse on dep 'ide_core' done

/ #

As for more complicated testing with involved dependencies and aliases, I managed to successfully unload and load snd_intel8x0 module with all it's dependencies, few of them depending on the replace call. The log is provided as an attachment.
Note that recursive module unloading should be performed only with modprobe -r, not with rmmod (module-init-tools version 3.4), but that belongs to another bug entry.
Comment 6 Denys Vlasenko 2009-09-12 13:57:10 UTC
Fixed in git, also will be in 1.15.1