Commit a89a8e24 authored by Rusty Russell's avatar Rusty Russell Committed by Linus Torvalds

[PATCH] Forced module unload

This is the logical counterpoint to the code which marks modules
"[unsafe]" when obsolete (racy) interfaces are used.  Allows "just
remove the damn thing" rmmod -f, and taints the kernel.

Mark it dangerous and experimental in the config file to make this
doubly clear.
parent bbeabef1
......@@ -102,6 +102,7 @@ extern const char *print_tainted(void);
#define TAINT_PROPRIETORY_MODULE (1<<0)
#define TAINT_FORCED_MODULE (1<<1)
#define TAINT_UNSAFE_SMP (1<<2)
#define TAINT_FORCED_RMMOD (1<<3)
extern void dump_stack(void);
......
......@@ -125,6 +125,16 @@ config MODULE_UNLOAD
anyway), which makes your kernel slightly smaller and
simpler. If unsure, say Y.
config MODULE_FORCE_UNLOAD
bool "Forced module unloading"
depends on MODULES && EXPERIMENTAL
help
This option allows you to force a module to unload, even if the
kernel believes it is unsafe: the kernel will remove the module
without waiting for anyone to stop using it (using the -f option to
rmmod). This is mainly for kernel developers and desparate users.
If unsure, say N.
config KMOD
bool "Kernel module loader"
depends on MODULES
......
......@@ -348,12 +348,24 @@ static unsigned int module_refcount(struct module *mod)
/* This exists whether we can unload or not */
static void free_module(struct module *mod);
#ifdef CONFIG_MODULE_FORCE_UNLOAD
static inline int try_force(unsigned int flags)
{
return (flags & O_TRUNC);
}
#else
static inline int try_force(unsigned int flags)
{
return 0;
}
#endif /* CONFIG_MODULE_FORCE_UNLOAD */
asmlinkage long
sys_delete_module(const char *name_user, unsigned int flags)
{
struct module *mod;
char name[MODULE_NAME_LEN];
int ret;
int ret, forced = 0;
if (!capable(CAP_SYS_MODULE))
return -EPERM;
......@@ -371,24 +383,29 @@ sys_delete_module(const char *name_user, unsigned int flags)
goto out;
}
if (!list_empty(&mod->modules_which_use_me)) {
/* Other modules depend on us: get rid of them first. */
ret = -EWOULDBLOCK;
goto out;
}
/* Already dying? */
if (!mod->live) {
/* FIXME: if (force), slam module count and wake up
waiter --RR */
DEBUGP("%s already dying\n", mod->name);
ret = -EBUSY;
goto out;
}
if (!mod->exit || mod->unsafe) {
forced = try_force(flags);
if (!forced) {
/* This module can't be removed */
ret = -EBUSY;
goto out;
}
if (!list_empty(&mod->modules_which_use_me)) {
/* Other modules depend on us: get rid of them first. */
ret = -EWOULDBLOCK;
goto out;
}
/* Stop the machine so refcounts can't move: irqs disabled. */
DEBUGP("Stopping refcounts...\n");
ret = stop_refcounts();
......@@ -396,9 +413,11 @@ sys_delete_module(const char *name_user, unsigned int flags)
goto out;
/* If it's not unused, quit unless we are told to block. */
if ((flags & O_NONBLOCK) && module_refcount(mod) != 0)
if ((flags & O_NONBLOCK) && module_refcount(mod) != 0) {
forced = try_force(flags);
if (!forced)
ret = -EWOULDBLOCK;
else {
} else {
mod->waiter = current;
mod->live = 0;
}
......@@ -407,6 +426,9 @@ sys_delete_module(const char *name_user, unsigned int flags)
if (ret != 0)
goto out;
if (forced)
goto destroy;
/* Since we might sleep for some time, drop the semaphore first */
up(&module_mutex);
for (;;) {
......@@ -421,10 +443,11 @@ sys_delete_module(const char *name_user, unsigned int flags)
DEBUGP("Regrabbing mutex...\n");
down(&module_mutex);
destroy:
/* Final destruction now noone is using it. */
if (mod->exit)
mod->exit();
free_module(mod);
ret = 0;
out:
up(&module_mutex);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment