X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=kernel%2Fkmod.c;h=1e79dfcbe9acb563ea8802b5ce4c484bd1427332;hb=7172c64a7cee4dfa95864f49c914f7ea8cf497c8;hp=ea62192b7597aff716b7d594aca8eb27e860eb33;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/kernel/kmod.c b/kernel/kmod.c index ea62192b7..1e79dfcbe 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -20,7 +20,6 @@ */ #define __KERNEL_SYSCALLS__ -#include #include #include #include @@ -115,34 +114,12 @@ int request_module(const char *fmt, ...) EXPORT_SYMBOL(request_module); #endif /* CONFIG_KMOD */ -#ifdef CONFIG_HOTPLUG -/* - hotplug path is set via /proc/sys - invoked by hotplug-aware bus drivers, - with call_usermodehelper - - argv [0] = hotplug_path; - argv [1] = "usb", "scsi", "pci", "network", etc; - ... plus optional type-specific parameters - argv [n] = 0; - - envp [*] = HOME, PATH; optional type-specific parameters - - a hotplug bus should invoke this for device add/remove - events. the command is expected to load drivers when - necessary, and may perform additional system setup. -*/ -char hotplug_path[KMOD_PATH_LEN] = "/sbin/hotplug"; - -EXPORT_SYMBOL(hotplug_path); - -#endif /* CONFIG_HOTPLUG */ - struct subprocess_info { struct completion *complete; char *path; char **argv; char **envp; + struct key *ring; int wait; int retval; }; @@ -150,26 +127,46 @@ struct subprocess_info { /* * This is the task which runs the usermode application */ -static int ____call_usermodehelper(void *data) +int +__exec_usermodehelper(char *path, char **argv, char **envp, struct key *ring) { - struct subprocess_info *sub_info = data; + struct key *new_session, *old_session; int retval; - cpumask_t mask = CPU_MASK_ALL; - /* Unblock all signals. */ + /* Unblock all signals and set the session keyring. */ + new_session = key_get(ring); flush_signals(current); spin_lock_irq(¤t->sighand->siglock); + old_session = __install_session_keyring(current, new_session); flush_signal_handlers(current, 1); sigemptyset(¤t->blocked); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - /* We can run anywhere, unlike our parent keventd(). */ - set_cpus_allowed(current, mask); + key_put(old_session); retval = -EPERM; if (current->fs->root) - retval = execve(sub_info->path, sub_info->argv,sub_info->envp); + retval = execve(path, argv, envp); + + return retval; +} + +EXPORT_SYMBOL_GPL(__exec_usermodehelper); + +/* + * This is the task which runs the usermode application + */ +static int ____call_usermodehelper(void *data) +{ + struct subprocess_info *sub_info = data; + int retval; + + /* We can run anywhere, unlike our parent keventd(). */ + set_cpus_allowed(current, CPU_MASK_ALL); + + retval = __exec_usermodehelper(sub_info->path, + sub_info->argv, sub_info->envp, sub_info->ring); /* Exec failed? */ sub_info->retval = retval; @@ -188,7 +185,7 @@ static int wait_for_helper(void *data) sa.sa.sa_handler = SIG_IGN; sa.sa.sa_flags = 0; siginitset(&sa.sa.sa_mask, sigmask(SIGCHLD)); - do_sigaction(SIGCHLD, &sa, (struct k_sigaction *)0); + do_sigaction(SIGCHLD, &sa, NULL); allow_signal(SIGCHLD); pid = kernel_thread(____call_usermodehelper, sub_info, SIGCHLD); @@ -216,11 +213,12 @@ static void __call_usermodehelper(void *data) { struct subprocess_info *sub_info = data; pid_t pid; + int wait = sub_info->wait; /* CLONE_VFORK: wait until the usermode helper has execve'd * successfully We need the data structures to stay around * until that is done. */ - if (sub_info->wait) + if (wait) pid = kernel_thread(wait_for_helper, sub_info, CLONE_FS | CLONE_FILES | SIGCHLD); else @@ -230,15 +228,16 @@ static void __call_usermodehelper(void *data) if (pid < 0) { sub_info->retval = pid; complete(sub_info->complete); - } else if (!sub_info->wait) + } else if (!wait) complete(sub_info->complete); } /** - * call_usermodehelper - start a usermode application + * call_usermodehelper_keys - start a usermode application * @path: pathname for the application * @argv: null-terminated argument list * @envp: null-terminated environment list + * @session_keyring: session keyring for process (NULL for an empty keyring) * @wait: wait for the application to finish and return status. * * Runs a user-space application. The application is started @@ -248,14 +247,16 @@ static void __call_usermodehelper(void *data) * Must be called from process context. Returns a negative error code * if program was not execed successfully, or 0. */ -int call_usermodehelper(char *path, char **argv, char **envp, int wait) +int call_usermodehelper_keys(char *path, char **argv, char **envp, + struct key *session_keyring, int wait) { - DECLARE_COMPLETION(done); + DECLARE_COMPLETION_ONSTACK(done); struct subprocess_info sub_info = { .complete = &done, .path = path, .argv = argv, .envp = envp, + .ring = session_keyring, .wait = wait, .retval = 0, }; @@ -271,12 +272,10 @@ int call_usermodehelper(char *path, char **argv, char **envp, int wait) wait_for_completion(&done); return sub_info.retval; } -EXPORT_SYMBOL(call_usermodehelper); +EXPORT_SYMBOL(call_usermodehelper_keys); -static __init int usermodehelper_init(void) +void __init usermodehelper_init(void) { khelper_wq = create_singlethread_workqueue("khelper"); BUG_ON(!khelper_wq); - return 0; } -core_initcall(usermodehelper_init);