From c353c3fb0700a3c17ea2b0237710a184232ccd7f Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Fri, 2 Feb 2007 16:39:12 +0100 Subject: Driver core: let request_module() send a /sys/modules/kmod/-uevent On recent systems, calls to /sbin/modprobe are handled by udev depending on the kind of device the kernel has discovered. This patch creates an uevent for the kernels internal request_module(), to let udev take control over the request, instead of forking the binary directly by the kernel. The direct execution of /sbin/modprobe can be disabled by setting: /sys/module/kmod/mod_request_helper (/proc/sys/kernel/modprobe) to an empty string, the same way /proc/sys/kernel/hotplug is disabled on an udev system. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- kernel/params.c | 1 + 1 file changed, 1 insertion(+) (limited to 'kernel/params.c') diff --git a/kernel/params.c b/kernel/params.c index 553cf7d6a4be..7d231c6c1334 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -714,6 +714,7 @@ static int __init param_sysfs_init(void) } param_sysfs_builtin(); + kmod_sysfs_init(); return 0; } -- cgit v1.2.3 From ef665c1a06be719ed9a6b0ad7967137258d9457a Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 13 Feb 2007 15:19:06 -0800 Subject: sysfs: fix build errors: uevent with CONFIG_SYSFS=n Fix source files to build with CONFIG_SYSFS=n. module_subsys is not available. SYSFS=n, MODULES=y: T:y SYSFS=n, MODULES=n: T:y SYSFS=y, MODULES=y: T:y SYSFS=y, MODULES=n: T:y Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- include/linux/module.h | 53 +++++++++++++++++++++++++++++++++++++-------- include/linux/moduleparam.h | 12 ++++++++++ kernel/module.c | 14 ++++++++---- kernel/params.c | 28 +++++++++++++----------- 4 files changed, 81 insertions(+), 26 deletions(-) (limited to 'kernel/params.c') diff --git a/include/linux/module.h b/include/linux/module.h index 419d3ef293dd..95679eb8571e 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -76,8 +76,6 @@ void sort_extable(struct exception_table_entry *start, struct exception_table_entry *finish); void sort_main_extable(void); -extern struct subsystem module_subsys; - #ifdef MODULE #define MODULE_GENERIC_TABLE(gtype,name) \ extern const struct gtype##_id __mod_##gtype##_table \ @@ -467,10 +465,6 @@ int unregister_module_notifier(struct notifier_block * nb); extern void print_modules(void); -struct device_driver; -void module_add_driver(struct module *, struct device_driver *); -void module_remove_driver(struct device_driver *); - #else /* !CONFIG_MODULES... */ #define EXPORT_SYMBOL(sym) #define EXPORT_SYMBOL_GPL(sym) @@ -568,18 +562,59 @@ static inline void print_modules(void) { } +#endif /* CONFIG_MODULES */ + struct device_driver; +#ifdef CONFIG_SYSFS struct module; -static inline void module_add_driver(struct module *module, struct device_driver *driver) +extern struct subsystem module_subsys; + +int mod_sysfs_init(struct module *mod); +int mod_sysfs_setup(struct module *mod, + struct kernel_param *kparam, + unsigned int num_params); +int module_add_modinfo_attrs(struct module *mod); +void module_remove_modinfo_attrs(struct module *mod); + +#else /* !CONFIG_SYSFS */ + +static inline int mod_sysfs_init(struct module *mod) { + return 0; } -static inline void module_remove_driver(struct device_driver *driver) +static inline int mod_sysfs_setup(struct module *mod, + struct kernel_param *kparam, + unsigned int num_params) { + return 0; } -#endif /* CONFIG_MODULES */ +static inline int module_add_modinfo_attrs(struct module *mod) +{ + return 0; +} + +static inline void module_remove_modinfo_attrs(struct module *mod) +{ } + +#endif /* CONFIG_SYSFS */ + +#if defined(CONFIG_SYSFS) && defined(CONFIG_MODULES) + +void module_add_driver(struct module *mod, struct device_driver *drv); +void module_remove_driver(struct device_driver *drv); + +#else /* not both CONFIG_SYSFS && CONFIG_MODULES */ + +static inline void module_add_driver(struct module *mod, struct device_driver *drv) +{ } + +static inline void module_remove_driver(struct device_driver *drv) +{ } + +#endif #define symbol_request(x) try_then_request_module(symbol_get(x), "symbol:" #x) diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index 4a189dadb160..b26b2e5fedc7 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h @@ -169,10 +169,22 @@ extern int param_get_string(char *buffer, struct kernel_param *kp); struct module; +#if defined(CONFIG_SYSFS) && defined(CONFIG_MODULES) extern int module_param_sysfs_setup(struct module *mod, struct kernel_param *kparam, unsigned int num_params); extern void module_param_sysfs_remove(struct module *mod); +#else +static inline int module_param_sysfs_setup(struct module *mod, + struct kernel_param *kparam, + unsigned int num_params) +{ + return 0; +} + +static inline void module_param_sysfs_remove(struct module *mod) +{ } +#endif #endif /* _LINUX_MODULE_PARAMS_H */ diff --git a/kernel/module.c b/kernel/module.c index e06b77af23fd..8c25b1a04fa6 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1074,7 +1074,8 @@ static inline void remove_sect_attrs(struct module *mod) } #endif /* CONFIG_KALLSYMS */ -static int module_add_modinfo_attrs(struct module *mod) +#ifdef CONFIG_SYSFS +int module_add_modinfo_attrs(struct module *mod) { struct module_attribute *attr; struct module_attribute *temp_attr; @@ -1100,7 +1101,7 @@ static int module_add_modinfo_attrs(struct module *mod) return error; } -static void module_remove_modinfo_attrs(struct module *mod) +void module_remove_modinfo_attrs(struct module *mod) { struct module_attribute *attr; int i; @@ -1115,8 +1116,10 @@ static void module_remove_modinfo_attrs(struct module *mod) } kfree(mod->modinfo_attrs); } +#endif -static int mod_sysfs_init(struct module *mod) +#ifdef CONFIG_SYSFS +int mod_sysfs_init(struct module *mod) { int err; @@ -1139,7 +1142,7 @@ out: return err; } -static int mod_sysfs_setup(struct module *mod, +int mod_sysfs_setup(struct module *mod, struct kernel_param *kparam, unsigned int num_params) { @@ -1175,6 +1178,7 @@ out_unreg: out: return err; } +#endif static void mod_kobject_remove(struct module *mod) { @@ -2348,6 +2352,7 @@ void print_modules(void) printk("\n"); } +#ifdef CONFIG_SYSFS static char *make_driver_name(struct device_driver *drv) { char *driver_name; @@ -2422,6 +2427,7 @@ void module_remove_driver(struct device_driver *drv) } } EXPORT_SYMBOL(module_remove_driver); +#endif #ifdef CONFIG_MODVERSIONS /* Generate the signature for struct module here, too, for modversions. */ diff --git a/kernel/params.c b/kernel/params.c index 7d231c6c1334..7a751570b56d 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -30,8 +30,6 @@ #define DEBUGP(fmt, a...) #endif -static struct kobj_type module_ktype; - static inline char dash2underscore(char c) { if (c == '-') @@ -391,6 +389,7 @@ struct module_param_attrs struct param_attribute attrs[0]; }; +#ifdef CONFIG_SYSFS #define to_param_attr(n) container_of(n, struct param_attribute, mattr); static ssize_t param_attr_show(struct module_attribute *mattr, @@ -426,6 +425,7 @@ static ssize_t param_attr_store(struct module_attribute *mattr, return len; return err; } +#endif #ifdef CONFIG_MODULES #define __modinit @@ -433,6 +433,7 @@ static ssize_t param_attr_store(struct module_attribute *mattr, #define __modinit __init #endif +#ifdef CONFIG_SYSFS /* * param_sysfs_setup - setup sysfs support for one module or KBUILD_MODNAME * @mk: struct module_kobject (contains parent kobject) @@ -500,9 +501,7 @@ param_sysfs_setup(struct module_kobject *mk, return mp; } - #ifdef CONFIG_MODULES - /* * module_param_sysfs_setup - setup sysfs support for one module * @mod: module @@ -625,7 +624,6 @@ static void __init param_sysfs_builtin(void) /* module-related sysfs stuff */ -#ifdef CONFIG_SYSFS #define to_module_attr(n) container_of(n, struct module_attribute, attr); #define to_module_kobject(n) container_of(n, struct module_kobject, kobj); @@ -673,6 +671,8 @@ static struct sysfs_ops module_sysfs_ops = { .store = module_attr_store, }; +static struct kobj_type module_ktype; + static int uevent_filter(struct kset *kset, struct kobject *kobj) { struct kobj_type *ktype = get_ktype(kobj); @@ -686,19 +686,12 @@ static struct kset_uevent_ops module_uevent_ops = { .filter = uevent_filter, }; -#else -static struct sysfs_ops module_sysfs_ops = { - .show = NULL, - .store = NULL, -}; -#endif +decl_subsys(module, &module_ktype, &module_uevent_ops); static struct kobj_type module_ktype = { .sysfs_ops = &module_sysfs_ops, }; -decl_subsys(module, &module_ktype, &module_uevent_ops); - /* * param_sysfs_init - wrapper for built-in params support */ @@ -720,6 +713,15 @@ static int __init param_sysfs_init(void) } subsys_initcall(param_sysfs_init); +#else +#if 0 +static struct sysfs_ops module_sysfs_ops = { + .show = NULL, + .store = NULL, +}; +#endif +#endif + EXPORT_SYMBOL(param_set_byte); EXPORT_SYMBOL(param_get_byte); EXPORT_SYMBOL(param_set_short); -- cgit v1.2.3 From dfff0a0671baf4e69fc676bf8150635407548288 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 23 Feb 2007 14:54:57 -0800 Subject: Revert "Driver core: let request_module() send a /sys/modules/kmod/-uevent" This reverts commit c353c3fb0700a3c17ea2b0237710a184232ccd7f. It turns out that we end up with a loop trying to load the unix module and calling netfilter to do that. Will redo the patch later to not have this loop. Acked-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- include/linux/kmod.h | 2 - kernel/kmod.c | 120 --------------------------------------------------- kernel/module.c | 26 +++++------ kernel/params.c | 1 - 4 files changed, 10 insertions(+), 139 deletions(-) (limited to 'kernel/params.c') diff --git a/include/linux/kmod.h b/include/linux/kmod.h index cc8e674ae27a..10f505c8431d 100644 --- a/include/linux/kmod.h +++ b/include/linux/kmod.h @@ -28,10 +28,8 @@ #ifdef CONFIG_KMOD /* modprobe exit status on success, -ve on error. Return value * usually useless though. */ -extern void kmod_sysfs_init(void); extern int request_module(const char * name, ...) __attribute__ ((format (printf, 1, 2))); #else -static inline void kmod_sysfs_init(void) {}; static inline int request_module(const char * name, ...) { return -ENOSYS; } #endif diff --git a/kernel/kmod.c b/kernel/kmod.c index f936108f2963..796276141e51 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -36,8 +36,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 +46,6 @@ static struct workqueue_struct *khelper_wq; modprobe_path is set via /proc/sys. */ char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe"; -static struct module_kobject kmod_mk; /** * request_module - try to load a kernel module @@ -78,11 +75,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 +82,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 +108,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 { diff --git a/kernel/module.c b/kernel/module.c index 1ecf08106381..f77e893e4620 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -653,11 +653,20 @@ static void wait_for_zero_refcount(struct module *mod) mutex_lock(&module_mutex); } -int delete_module(const char *name, unsigned int flags) +asmlinkage long +sys_delete_module(const char __user *name_user, unsigned int flags) { struct module *mod; + char name[MODULE_NAME_LEN]; int ret, forced = 0; + if (!capable(CAP_SYS_MODULE)) + return -EPERM; + + if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0) + return -EFAULT; + name[MODULE_NAME_LEN-1] = '\0'; + if (mutex_lock_interruptible(&module_mutex) != 0) return -EINTR; @@ -718,21 +727,6 @@ int delete_module(const char *name, unsigned int flags) return ret; } -asmlinkage long -sys_delete_module(const char __user *name_user, unsigned int flags) -{ - char name[MODULE_NAME_LEN]; - - if (!capable(CAP_SYS_MODULE)) - return -EPERM; - - if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0) - return -EFAULT; - name[MODULE_NAME_LEN-1] = '\0'; - - return delete_module(name, flags); -} - static void print_unload_info(struct seq_file *m, struct module *mod) { struct module_use *use; diff --git a/kernel/params.c b/kernel/params.c index 7a751570b56d..e265b13195b1 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -707,7 +707,6 @@ static int __init param_sysfs_init(void) } param_sysfs_builtin(); - kmod_sysfs_init(); return 0; } -- cgit v1.2.3 From fe20e581a72979917e35d5146458ceba79be391f Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 11 Apr 2007 23:28:41 -0700 Subject: [PATCH] fix kernel oops with badly formatted module option Catch malformed kernel parameter usage of "param = value". Spaces are not supported, but don't cause a kernel fault on such usage, just report an error. Signed-off-by: Randy Dunlap Acked-by: Larry Finger Acked-by: Rusty Russell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/params.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'kernel/params.c') diff --git a/kernel/params.c b/kernel/params.c index e265b13195b1..1fc4ac746cd8 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -356,6 +356,10 @@ int param_set_copystring(const char *val, struct kernel_param *kp) { struct kparam_string *kps = kp->arg; + if (!val) { + printk(KERN_ERR "%s: missing param set value\n", kp->name); + return -EINVAL; + } if (strlen(val)+1 > kps->maxlen) { printk(KERN_ERR "%s: string doesn't fit in %u chars.\n", kp->name, kps->maxlen-1); -- cgit v1.2.3