X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;ds=sidebyside;f=kernel%2Fkmod.c;h=4d32eb077179a2babd3f49b9f31631d4c6e27bb7;hb=0e9871df2389560e94ba01e40959140ee56def4b;hp=9f923f8ce6a0cd3c225f73eb79c865777ac60967;hpb=2370965c5065b24b28b5ba09b60ddfbfb6d7649b;p=powerpc.git diff --git a/kernel/kmod.c b/kernel/kmod.c index 9f923f8ce6..4d32eb0771 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -36,8 +35,6 @@ #include #include -extern int delete_module(const char *name, unsigned int flags); - extern int max_threads; static struct workqueue_struct *khelper_wq; @@ -48,7 +45,6 @@ static struct workqueue_struct *khelper_wq; modprobe_path is set via /proc/sys. */ char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe"; -struct module_kobject kmod_mk; /** * request_module - try to load a kernel module @@ -78,11 +74,6 @@ int request_module(const char *fmt, ...) static atomic_t kmod_concurrent = ATOMIC_INIT(0); #define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */ static int kmod_loop_msg; - char modalias[16 + MODULE_NAME_LEN] = "MODALIAS="; - char *uevent_envp[2] = { - modalias, - NULL - }; va_start(args, fmt); ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args); @@ -90,12 +81,6 @@ int request_module(const char *fmt, ...) if (ret >= MODULE_NAME_LEN) return -ENAMETOOLONG; - strcpy(&modalias[strlen("MODALIAS=")], module_name); - kobject_uevent_env(&kmod_mk.kobj, KOBJ_CHANGE, uevent_envp); - - if (modprobe_path[0] == '\0') - goto out; - /* If modprobe needs a service that is in a module, we get a recursive * loop. Limit the number of running kmod threads to max_threads/2 or * MAX_KMOD_CONCURRENT, whichever is the smaller. A cleaner method @@ -122,115 +107,9 @@ int request_module(const char *fmt, ...) ret = call_usermodehelper(modprobe_path, argv, envp, 1); atomic_dec(&kmod_concurrent); -out: return ret; } EXPORT_SYMBOL(request_module); - -static ssize_t store_mod_request(struct module_attribute *mattr, - struct module *mod, - const char *buffer, size_t count) -{ - char name[MODULE_NAME_LEN]; - int ret; - - if (count < 1 || count+1 > MODULE_NAME_LEN) - return -EINVAL; - memcpy(name, buffer, count); - name[count] = '\0'; - if (name[count-1] == '\n') - name[count-1] = '\0'; - - ret = request_module(name); - if (ret < 0) - return ret; - return count; -} - -static struct module_attribute mod_request = { - .attr = { .name = "mod_request", .mode = S_IWUSR, .owner = THIS_MODULE }, - .store = store_mod_request, -}; - -#ifdef CONFIG_MODULE_UNLOAD -static ssize_t store_mod_unload(struct module_attribute *mattr, - struct module *mod, - const char *buffer, size_t count) -{ - char name[MODULE_NAME_LEN]; - int ret; - - if (count < 1 || count+1 > MODULE_NAME_LEN) - return -EINVAL; - memcpy(name, buffer, count); - name[count] = '\0'; - if (name[count-1] == '\n') - name[count-1] = '\0'; - - ret = delete_module(name, O_NONBLOCK); - if (ret < 0) - return ret; - return count; -} - -static struct module_attribute mod_unload = { - .attr = { .name = "mod_unload", .mode = S_IWUSR, .owner = THIS_MODULE }, - .store = store_mod_unload, -}; -#endif - -static ssize_t show_mod_request_helper(struct module_attribute *mattr, - struct module *mod, - char *buffer) -{ - return sprintf(buffer, "%s\n", modprobe_path); -} - -static ssize_t store_mod_request_helper(struct module_attribute *mattr, - struct module *mod, - const char *buffer, size_t count) -{ - if (count < 1 || count+1 > KMOD_PATH_LEN) - return -EINVAL; - memcpy(modprobe_path, buffer, count); - modprobe_path[count] = '\0'; - if (modprobe_path[count-1] == '\n') - modprobe_path[count-1] = '\0'; - return count; -} - -static struct module_attribute mod_request_helper = { - .attr = { - .name = "mod_request_helper", - .mode = S_IWUSR | S_IRUGO, - .owner = THIS_MODULE - }, - .show = show_mod_request_helper, - .store = store_mod_request_helper, -}; - -void __init kmod_sysfs_init(void) -{ - int ret; - - kmod_mk.mod = THIS_MODULE; - kobj_set_kset_s(&kmod_mk, module_subsys); - kobject_set_name(&kmod_mk.kobj, "kmod"); - kobject_init(&kmod_mk.kobj); - ret = kobject_add(&kmod_mk.kobj); - if (ret < 0) - goto out; - - ret = sysfs_create_file(&kmod_mk.kobj, &mod_request_helper.attr); - ret = sysfs_create_file(&kmod_mk.kobj, &mod_request.attr); -#ifdef CONFIG_MODULE_UNLOAD - ret = sysfs_create_file(&kmod_mk.kobj, &mod_unload.attr); -#endif - - kobject_uevent(&kmod_mk.kobj, KOBJ_ADD); -out: - return; -} #endif /* CONFIG_KMOD */ struct subprocess_info { @@ -256,7 +135,6 @@ static int ____call_usermodehelper(void *data) /* Unblock all signals and set the session keyring. */ new_session = key_get(sub_info->ring); - flush_signals(current); spin_lock_irq(¤t->sighand->siglock); old_session = __install_session_keyring(current, new_session); flush_signal_handlers(current, 1); @@ -286,6 +164,12 @@ static int ____call_usermodehelper(void *data) /* We can run anywhere, unlike our parent keventd(). */ set_cpus_allowed(current, CPU_MASK_ALL); + /* + * Our parent is keventd, which runs with elevated scheduling priority. + * Avoid propagating that into the userspace child. + */ + set_user_nice(current, 0); + retval = -EPERM; if (current->fs->root) retval = kernel_execve(sub_info->path, @@ -301,14 +185,9 @@ static int wait_for_helper(void *data) { struct subprocess_info *sub_info = data; pid_t pid; - struct k_sigaction sa; /* Install a handler: if SIGCLD isn't handled sys_wait4 won't * populate the status, but will return -ECHILD. */ - sa.sa.sa_handler = SIG_IGN; - sa.sa.sa_flags = 0; - siginitset(&sa.sa.sa_mask, sigmask(SIGCHLD)); - do_sigaction(SIGCHLD, &sa, NULL); allow_signal(SIGCHLD); pid = kernel_thread(____call_usermodehelper, sub_info, SIGCHLD);