While commit 42b32d30c38e ("modprobe: Fix holders removal", 2022-03-29) already implements removing first-level holders, indirect holders were not evaluated. In a simple module dependency chain like module3 depends on module2 module2 depends on module1 'modprobe -r --remove-holders module1' was only considering module2 and module1 and thus had to fail as module3 was still loaded and blocking removal of module2. By doing recursive depth-first removal this can be fixed for such simple dependency. (modprobe.8 man page is not touched as it does not yet have anything about --remove-holders.) Signed-off-by: Nicolas Schier <n.schier@xxxxxx> --- To: linux-modules@xxxxxxxxxxxxxxx Cc: Lucas De Marchi <lucas.de.marchi@xxxxxxxxx> --- Changes in v2: * Several fixes (memleak, attempt to remove modules that were just removed, --dry-run support) * new patch: Add rudimentary implementation of sysfs tree modification to delete_module() * new patch: Add two tests regarding --remove-holders to testsuite/test-modprobe.c * Link to v1: https://lore.kernel.org/r/20230309-remove-holders-recursively-v1-1-c27cdba1edbf@xxxxxx --- Nicolas Schier (3): kmod: modprobe: Remove holders recursively testsuite: delete_module: Roughly implement fake-removal in sysfs tree testsuite: modprobe: Add test for --remove-holders Makefile.am | 1 + testsuite/delete_module.c | 262 ++++++++++++++++++++- testsuite/module-playground/Makefile | 6 + testsuite/module-playground/mod-dep-chain-a.c | 21 ++ testsuite/module-playground/mod-dep-chain-b.c | 22 ++ testsuite/module-playground/mod-dep-chain-c.c | 22 ++ testsuite/module-playground/mod-dep-chain.h | 8 + .../remove-holders/lib/modules/6.2/modules.alias | 1 + .../lib/modules/6.2/modules.alias.bin | Bin 0 -> 12 bytes .../lib/modules/6.2/modules.builtin.alias.bin | 0 .../lib/modules/6.2/modules.builtin.bin | 0 .../remove-holders/lib/modules/6.2/modules.dep | 3 + .../remove-holders/lib/modules/6.2/modules.dep.bin | Bin 0 -> 229 bytes .../remove-holders/lib/modules/6.2/modules.devname | 0 .../remove-holders/lib/modules/6.2/modules.softdep | 1 + .../remove-holders/lib/modules/6.2/modules.symbols | 4 + .../lib/modules/6.2/modules.symbols.bin | Bin 0 -> 143 bytes .../test-modprobe/remove-holders/proc/modules | 3 + .../sys/module/mod_dep_chain_a/coresize | 1 + .../module/mod_dep_chain_a/holders/mod_dep_chain_b | 1 + .../sys/module/mod_dep_chain_a/initsize | 1 + .../sys/module/mod_dep_chain_a/initstate | 1 + .../sys/module/mod_dep_chain_a/notes/.note.Linux | Bin 0 -> 60 bytes .../mod_dep_chain_a/notes/.note.gnu.build-id | Bin 0 -> 36 bytes .../sys/module/mod_dep_chain_a/refcnt | 1 + .../sections/.gnu.linkonce.this_module | 1 + .../sys/module/mod_dep_chain_a/sections/.init.data | 1 + .../module/mod_dep_chain_a/sections/.note.Linux | 1 + .../mod_dep_chain_a/sections/.note.gnu.build-id | 1 + .../module/mod_dep_chain_a/sections/.orc_unwind | 1 + .../module/mod_dep_chain_a/sections/.orc_unwind_ip | 1 + .../module/mod_dep_chain_a/sections/.return_sites | 1 + .../module/mod_dep_chain_a/sections/.rodata.str1.1 | 1 + .../sys/module/mod_dep_chain_a/sections/.strtab | 1 + .../sys/module/mod_dep_chain_a/sections/.symtab | 1 + .../module/mod_dep_chain_a/sections/.text.unlikely | 1 + .../sys/module/mod_dep_chain_a/sections/__kcrctab | 1 + .../sys/module/mod_dep_chain_a/sections/__ksymtab | 1 + .../mod_dep_chain_a/sections/__ksymtab_strings | 1 + .../module/mod_dep_chain_a/sections/__mcount_loc | 1 + .../sys/module/mod_dep_chain_a/taint | 1 + .../sys/module/mod_dep_chain_b/coresize | 1 + .../module/mod_dep_chain_b/holders/mod_dep_chain_c | 1 + .../sys/module/mod_dep_chain_b/initsize | 1 + .../sys/module/mod_dep_chain_b/initstate | 1 + .../sys/module/mod_dep_chain_b/notes/.note.Linux | Bin 0 -> 60 bytes .../mod_dep_chain_b/notes/.note.gnu.build-id | Bin 0 -> 36 bytes .../sys/module/mod_dep_chain_b/refcnt | 1 + .../sections/.gnu.linkonce.this_module | 1 + .../sys/module/mod_dep_chain_b/sections/.init.data | 1 + .../module/mod_dep_chain_b/sections/.note.Linux | 1 + .../mod_dep_chain_b/sections/.note.gnu.build-id | 1 + .../module/mod_dep_chain_b/sections/.orc_unwind | 1 + .../module/mod_dep_chain_b/sections/.orc_unwind_ip | 1 + .../module/mod_dep_chain_b/sections/.return_sites | 1 + .../module/mod_dep_chain_b/sections/.rodata.str1.8 | 1 + .../sys/module/mod_dep_chain_b/sections/.strtab | 1 + .../sys/module/mod_dep_chain_b/sections/.symtab | 1 + .../module/mod_dep_chain_b/sections/.text.unlikely | 1 + .../sys/module/mod_dep_chain_b/sections/__kcrctab | 1 + .../sys/module/mod_dep_chain_b/sections/__ksymtab | 1 + .../mod_dep_chain_b/sections/__ksymtab_strings | 1 + .../module/mod_dep_chain_b/sections/__mcount_loc | 1 + .../sys/module/mod_dep_chain_b/taint | 1 + .../sys/module/mod_dep_chain_c/coresize | 1 + .../sys/module/mod_dep_chain_c/holders/.gitignore | 0 .../sys/module/mod_dep_chain_c/initsize | 1 + .../sys/module/mod_dep_chain_c/initstate | 1 + .../sys/module/mod_dep_chain_c/notes/.note.Linux | Bin 0 -> 60 bytes .../mod_dep_chain_c/notes/.note.gnu.build-id | Bin 0 -> 36 bytes .../sys/module/mod_dep_chain_c/refcnt | 1 + .../sys/module/mod_dep_chain_c/taint | 1 + .../remove-single/lib/modules/6.2/modules.alias | 1 + .../lib/modules/6.2/modules.alias.bin | Bin 0 -> 12 bytes .../lib/modules/6.2/modules.builtin.alias.bin | 0 .../lib/modules/6.2/modules.builtin.bin | 0 .../remove-single/lib/modules/6.2/modules.dep | 3 + .../remove-single/lib/modules/6.2/modules.dep.bin | Bin 0 -> 229 bytes .../remove-single/lib/modules/6.2/modules.devname | 0 .../remove-single/lib/modules/6.2/modules.softdep | 1 + .../remove-single/lib/modules/6.2/modules.symbols | 4 + .../lib/modules/6.2/modules.symbols.bin | Bin 0 -> 143 bytes .../test-modprobe/remove-single/proc/modules | 3 + .../sys/module/mod_dep_chain_a/coresize | 1 + .../module/mod_dep_chain_a/holders/mod_dep_chain_b | 1 + .../sys/module/mod_dep_chain_a/initsize | 1 + .../sys/module/mod_dep_chain_a/initstate | 1 + .../sys/module/mod_dep_chain_a/notes/.note.Linux | Bin 0 -> 60 bytes .../mod_dep_chain_a/notes/.note.gnu.build-id | Bin 0 -> 36 bytes .../sys/module/mod_dep_chain_a/refcnt | 1 + .../sections/.gnu.linkonce.this_module | 1 + .../sys/module/mod_dep_chain_a/sections/.init.data | 1 + .../module/mod_dep_chain_a/sections/.note.Linux | 1 + .../mod_dep_chain_a/sections/.note.gnu.build-id | 1 + .../module/mod_dep_chain_a/sections/.orc_unwind | 1 + .../module/mod_dep_chain_a/sections/.orc_unwind_ip | 1 + .../module/mod_dep_chain_a/sections/.return_sites | 1 + .../module/mod_dep_chain_a/sections/.rodata.str1.1 | 1 + .../sys/module/mod_dep_chain_a/sections/.strtab | 1 + .../sys/module/mod_dep_chain_a/sections/.symtab | 1 + .../module/mod_dep_chain_a/sections/.text.unlikely | 1 + .../sys/module/mod_dep_chain_a/sections/__kcrctab | 1 + .../sys/module/mod_dep_chain_a/sections/__ksymtab | 1 + .../mod_dep_chain_a/sections/__ksymtab_strings | 1 + .../module/mod_dep_chain_a/sections/__mcount_loc | 1 + .../remove-single/sys/module/mod_dep_chain_a/taint | 1 + .../sys/module/mod_dep_chain_b/coresize | 1 + .../module/mod_dep_chain_b/holders/mod_dep_chain_c | 1 + .../sys/module/mod_dep_chain_b/initsize | 1 + .../sys/module/mod_dep_chain_b/initstate | 1 + .../sys/module/mod_dep_chain_b/notes/.note.Linux | Bin 0 -> 60 bytes .../mod_dep_chain_b/notes/.note.gnu.build-id | Bin 0 -> 36 bytes .../sys/module/mod_dep_chain_b/refcnt | 1 + .../sections/.gnu.linkonce.this_module | 1 + .../sys/module/mod_dep_chain_b/sections/.init.data | 1 + .../module/mod_dep_chain_b/sections/.note.Linux | 1 + .../mod_dep_chain_b/sections/.note.gnu.build-id | 1 + .../module/mod_dep_chain_b/sections/.orc_unwind | 1 + .../module/mod_dep_chain_b/sections/.orc_unwind_ip | 1 + .../module/mod_dep_chain_b/sections/.return_sites | 1 + .../module/mod_dep_chain_b/sections/.rodata.str1.8 | 1 + .../sys/module/mod_dep_chain_b/sections/.strtab | 1 + .../sys/module/mod_dep_chain_b/sections/.symtab | 1 + .../module/mod_dep_chain_b/sections/.text.unlikely | 1 + .../sys/module/mod_dep_chain_b/sections/__kcrctab | 1 + .../sys/module/mod_dep_chain_b/sections/__ksymtab | 1 + .../mod_dep_chain_b/sections/__ksymtab_strings | 1 + .../module/mod_dep_chain_b/sections/__mcount_loc | 1 + .../remove-single/sys/module/mod_dep_chain_b/taint | 1 + .../sys/module/mod_dep_chain_c/coresize | 1 + .../sys/module/mod_dep_chain_c/holders/.gitignore | 0 .../sys/module/mod_dep_chain_c/initsize | 1 + .../sys/module/mod_dep_chain_c/initstate | 1 + .../sys/module/mod_dep_chain_c/notes/.note.Linux | Bin 0 -> 60 bytes .../mod_dep_chain_c/notes/.note.gnu.build-id | Bin 0 -> 36 bytes .../sys/module/mod_dep_chain_c/refcnt | 1 + .../remove-single/sys/module/mod_dep_chain_c/taint | 1 + testsuite/setup-rootfs.sh | 3 + testsuite/test-modprobe.c | 55 +++++ tools/modprobe.c | 44 +++- 140 files changed, 551 insertions(+), 11 deletions(-) --- base-commit: 3d1bd339ab942ea47e60f053f4b11b0c47ff082b change-id: 20230309-remove-holders-recursively-f667f32e2a7d Best regards, -- Nicolas Schier