]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 5 Sep 2013 00:34:29 +0000 (17:34 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 5 Sep 2013 00:34:29 +0000 (17:34 -0700)
Pull module updates from Rusty Russell:
 "Minor fixes mainly, including a potential use-after-free on remove
  found by CONFIG_DEBUG_KOBJECT_RELEASE which may be theoretical"

* tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux:
  module: Fix mod->mkobj.kobj potentially freed too early
  kernel/params.c: use scnprintf() instead of sprintf()
  kernel/module.c: use scnprintf() instead of sprintf()
  module/lsm: Have apparmor module parameters work with no args
  module: Add NOARG flag for ops with param_set_bool_enable_only() set function
  module: Add flag to allow mod params to have no arguments
  modules: add support for soft module dependencies
  scripts/mod/modpost.c: permit '.cranges' secton for sh64 architecture.
  module: fix sprintf format specifier in param_get_byte()

include/linux/module.h
include/linux/moduleparam.h
kernel/module.c
kernel/params.c
scripts/mod/modpost.c
security/apparmor/lsm.c

index 46f1ea01e6f62161db550b13be8a2ed85246219a..05f2447f8c15ba5c13b2ec329baf6feaea0b031e 100644 (file)
@@ -42,6 +42,7 @@ struct module_kobject {
        struct module *mod;
        struct kobject *drivers_dir;
        struct module_param_attrs *mp;
+       struct completion *kobj_completion;
 };
 
 struct module_attribute {
@@ -97,6 +98,11 @@ extern const struct gtype##_id __mod_##gtype##_table         \
 /* For userspace: you can also call me... */
 #define MODULE_ALIAS(_alias) MODULE_INFO(alias, _alias)
 
+/* Soft module dependencies. See man modprobe.d for details.
+ * Example: MODULE_SOFTDEP("pre: module-foo module-bar post: module-baz")
+ */
+#define MODULE_SOFTDEP(_softdep) MODULE_INFO(softdep, _softdep)
+
 /*
  * The following license idents are currently accepted as indicating free
  * software modules
index 27d9da3f86ffe91c9d06aa3dc779902adbc620ad..c3eb102a9cc81d8ed97f11deb9584aa71830b1c5 100644 (file)
@@ -36,7 +36,18 @@ static const char __UNIQUE_ID(name)[]                                          \
 
 struct kernel_param;
 
+/*
+ * Flags available for kernel_param_ops
+ *
+ * NOARG - the parameter allows for no argument (foo instead of foo=1)
+ */
+enum {
+       KERNEL_PARAM_FL_NOARG = (1 << 0)
+};
+
 struct kernel_param_ops {
+       /* How the ops should behave */
+       unsigned int flags;
        /* Returns 0, or -errno.  arg is in kp->arg. */
        int (*set)(const char *val, const struct kernel_param *kp);
        /* Returns length written or -errno.  Buffer is 4k (ie. be short!) */
@@ -187,7 +198,7 @@ struct kparam_array
 /* Obsolete - use module_param_cb() */
 #define module_param_call(name, set, get, arg, perm)                   \
        static struct kernel_param_ops __param_ops_##name =             \
-                { (void *)set, (void *)get };                          \
+               { 0, (void *)set, (void *)get };                        \
        __module_param_call(MODULE_PARAM_PREFIX,                        \
                            name, &__param_ops_##name, arg,             \
                            (perm) + sizeof(__check_old_set_param(set))*0, -1)
index 206915830d2993bc54124b0fecf09abadac08a0f..9f5ddae72f4420623958f9ed9410630452d31715 100644 (file)
@@ -136,6 +136,7 @@ static int param_set_bool_enable_only(const char *val,
 }
 
 static const struct kernel_param_ops param_ops_bool_enable_only = {
+       .flags = KERNEL_PARAM_FL_NOARG,
        .set = param_set_bool_enable_only,
        .get = param_get_bool,
 };
@@ -603,7 +604,7 @@ static void setup_modinfo_##field(struct module *mod, const char *s)  \
 static ssize_t show_modinfo_##field(struct module_attribute *mattr,   \
                        struct module_kobject *mk, char *buffer)      \
 {                                                                     \
-       return sprintf(buffer, "%s\n", mk->mod->field);               \
+       return scnprintf(buffer, PAGE_SIZE, "%s\n", mk->mod->field);  \
 }                                                                     \
 static int modinfo_##field##_exists(struct module *mod)               \
 {                                                                     \
@@ -1611,6 +1612,14 @@ static void module_remove_modinfo_attrs(struct module *mod)
        kfree(mod->modinfo_attrs);
 }
 
+static void mod_kobject_put(struct module *mod)
+{
+       DECLARE_COMPLETION_ONSTACK(c);
+       mod->mkobj.kobj_completion = &c;
+       kobject_put(&mod->mkobj.kobj);
+       wait_for_completion(&c);
+}
+
 static int mod_sysfs_init(struct module *mod)
 {
        int err;
@@ -1638,7 +1647,7 @@ static int mod_sysfs_init(struct module *mod)
        err = kobject_init_and_add(&mod->mkobj.kobj, &module_ktype, NULL,
                                   "%s", mod->name);
        if (err)
-               kobject_put(&mod->mkobj.kobj);
+               mod_kobject_put(mod);
 
        /* delay uevent until full sysfs population */
 out:
@@ -1682,7 +1691,7 @@ static int mod_sysfs_setup(struct module *mod,
 out_unreg_holders:
        kobject_put(mod->holders_dir);
 out_unreg:
-       kobject_put(&mod->mkobj.kobj);
+       mod_kobject_put(mod);
 out:
        return err;
 }
@@ -1691,7 +1700,7 @@ static void mod_sysfs_fini(struct module *mod)
 {
        remove_notes_attrs(mod);
        remove_sect_attrs(mod);
-       kobject_put(&mod->mkobj.kobj);
+       mod_kobject_put(mod);
 }
 
 #else /* !CONFIG_SYSFS */
index 440e65d1a544c2d7bea49efbb45c1fbd2fde3a73..501bde4f3bee1476e1b0b293dda516dc815da680 100644 (file)
@@ -103,8 +103,8 @@ static int parse_one(char *param,
                            || params[i].level > max_level)
                                return 0;
                        /* No one handled NULL, so do it here. */
-                       if (!val && params[i].ops->set != param_set_bool
-                           && params[i].ops->set != param_set_bint)
+                       if (!val &&
+                           !(params[i].ops->flags & KERNEL_PARAM_FL_NOARG))
                                return -EINVAL;
                        pr_debug("handling %s with %p\n", param,
                                params[i].ops->set);
@@ -241,7 +241,8 @@ int parse_args(const char *doing,
        }                                                               \
        int param_get_##name(char *buffer, const struct kernel_param *kp) \
        {                                                               \
-               return sprintf(buffer, format, *((type *)kp->arg));     \
+               return scnprintf(buffer, PAGE_SIZE, format,             \
+                               *((type *)kp->arg));                    \
        }                                                               \
        struct kernel_param_ops param_ops_##name = {                    \
                .set = param_set_##name,                                \
@@ -252,7 +253,7 @@ int parse_args(const char *doing,
        EXPORT_SYMBOL(param_ops_##name)
 
 
-STANDARD_PARAM_DEF(byte, unsigned char, "%c", unsigned long, strict_strtoul);
+STANDARD_PARAM_DEF(byte, unsigned char, "%hhu", unsigned long, strict_strtoul);
 STANDARD_PARAM_DEF(short, short, "%hi", long, strict_strtol);
 STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", unsigned long, strict_strtoul);
 STANDARD_PARAM_DEF(int, int, "%i", long, strict_strtol);
@@ -285,7 +286,7 @@ EXPORT_SYMBOL(param_set_charp);
 
 int param_get_charp(char *buffer, const struct kernel_param *kp)
 {
-       return sprintf(buffer, "%s", *((char **)kp->arg));
+       return scnprintf(buffer, PAGE_SIZE, "%s", *((char **)kp->arg));
 }
 EXPORT_SYMBOL(param_get_charp);
 
@@ -320,6 +321,7 @@ int param_get_bool(char *buffer, const struct kernel_param *kp)
 EXPORT_SYMBOL(param_get_bool);
 
 struct kernel_param_ops param_ops_bool = {
+       .flags = KERNEL_PARAM_FL_NOARG,
        .set = param_set_bool,
        .get = param_get_bool,
 };
@@ -370,6 +372,7 @@ int param_set_bint(const char *val, const struct kernel_param *kp)
 EXPORT_SYMBOL(param_set_bint);
 
 struct kernel_param_ops param_ops_bint = {
+       .flags = KERNEL_PARAM_FL_NOARG,
        .set = param_set_bint,
        .get = param_get_int,
 };
@@ -827,7 +830,7 @@ ssize_t __modver_version_show(struct module_attribute *mattr,
        struct module_version_attribute *vattr =
                container_of(mattr, struct module_version_attribute, mattr);
 
-       return sprintf(buf, "%s\n", vattr->version);
+       return scnprintf(buf, PAGE_SIZE, "%s\n", vattr->version);
 }
 
 extern const struct module_version_attribute *__start___modver[];
@@ -912,7 +915,14 @@ static const struct kset_uevent_ops module_uevent_ops = {
 struct kset *module_kset;
 int module_sysfs_initialized;
 
+static void module_kobj_release(struct kobject *kobj)
+{
+       struct module_kobject *mk = to_module_kobject(kobj);
+       complete(mk->kobj_completion);
+}
+
 struct kobj_type module_ktype = {
+       .release   =    module_kobj_release,
        .sysfs_ops =    &module_sysfs_ops,
 };
 
index 62164348ecf7104e0a91671430702efbfb5fd610..8247979e8f64dd2eef5671544d3b39e8ed3487fc 100644 (file)
@@ -821,6 +821,7 @@ static const char *section_white_list[] =
 {
        ".comment*",
        ".debug*",
+       ".cranges",             /* sh64 */
        ".zdebug*",             /* Compressed debug sections. */
        ".GCC-command-line",    /* mn10300 */
        ".GCC.command.line",    /* record-gcc-switches, non mn10300 */
index 2e2a0dd4a73f1234425ded75027baea3b1e0b03e..e3a704c75ef68e74b5dadad2be437f8c2b6640d4 100644 (file)
@@ -666,6 +666,7 @@ static int param_set_aabool(const char *val, const struct kernel_param *kp);
 static int param_get_aabool(char *buffer, const struct kernel_param *kp);
 #define param_check_aabool param_check_bool
 static struct kernel_param_ops param_ops_aabool = {
+       .flags = KERNEL_PARAM_FL_NOARG,
        .set = param_set_aabool,
        .get = param_get_aabool
 };
@@ -682,6 +683,7 @@ static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp
 static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp);
 #define param_check_aalockpolicy param_check_bool
 static struct kernel_param_ops param_ops_aalockpolicy = {
+       .flags = KERNEL_PARAM_FL_NOARG,
        .set = param_set_aalockpolicy,
        .get = param_get_aalockpolicy
 };