summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-10-07 20:17:38 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-07 20:17:38 -0400
commitbdf428feb225229b1d4715b45bbdad4a934cd89c (patch)
tree9bc47e348c2081fd46c0f7d715780ce294a6953d
parenta40a7201a4584a66ab234ba1006472be952f20e0 (diff)
parent184c3fc3f52fb75800deb76deffb70907d1f76ea (diff)
Merge tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux
Pull module update from Rusty Russell: "Nothing major: support for compressing modules, and auto-tainting params. PS. My virtio-next tree is empty: DaveM took the patches I had. There might be a virtio-rng starvation fix, but so far it's a bit voodoo so I will get to that in the next two days or it will wait" * tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux: moduleparam: Resolve missing-field-initializer warning kbuild: handle module compression while running 'make modules_install'. modinst: wrap long lines in order to enhance cmd_modules_install modsign: lookup lines ending in .ko in .mod files modpost: simplify file name generation of *.mod.c files modpost: reduce visibility of symbols and constify r/o arrays param: check for tainting before calling set op. drm/i915: taint the kernel if unsafe module parameters are set module: add module_param_unsafe and module_param_named_unsafe module: make it possible to have unsafe, tainting module params module: rename KERNEL_PARAM_FL_NOARG to avoid confusion
-rw-r--r--Makefile15
-rw-r--r--drivers/gpu/drm/i915/i915_params.c8
-rw-r--r--drivers/tty/serial/8250/8250_core.c2
-rw-r--r--include/linux/moduleparam.h50
-rw-r--r--init/Kconfig43
-rw-r--r--kernel/module.c2
-rw-r--r--kernel/params.c17
-rw-r--r--scripts/Makefile.modinst7
-rw-r--r--scripts/Makefile.modsign2
-rw-r--r--scripts/mod/modpost.c25
-rw-r--r--security/apparmor/lsm.c4
11 files changed, 139 insertions, 36 deletions
diff --git a/Makefile b/Makefile
index b77de27e58f..5826c02842c 100644
--- a/Makefile
+++ b/Makefile
@@ -842,6 +842,21 @@ mod_strip_cmd = true
endif # INSTALL_MOD_STRIP
export mod_strip_cmd
+# CONFIG_MODULE_COMPRESS, if defined, will cause module to be compressed
+# after they are installed in agreement with CONFIG_MODULE_COMPRESS_GZIP
+# or CONFIG_MODULE_COMPRESS_XZ.
+
+mod_compress_cmd = true
+ifdef CONFIG_MODULE_COMPRESS
+ ifdef CONFIG_MODULE_COMPRESS_GZIP
+ mod_compress_cmd = gzip -n
+ endif # CONFIG_MODULE_COMPRESS_GZIP
+ ifdef CONFIG_MODULE_COMPRESS_XZ
+ mod_compress_cmd = xz
+ endif # CONFIG_MODULE_COMPRESS_XZ
+endif # CONFIG_MODULE_COMPRESS
+export mod_compress_cmd
+
# Select initial ramdisk compression format, default is gzip(1).
# This shall be used by the dracut(8) tool while creating an initramfs image.
#
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index 7f84dd263ee..9842fd2e742 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -66,12 +66,12 @@ module_param_named(powersave, i915.powersave, int, 0600);
MODULE_PARM_DESC(powersave,
"Enable powersavings, fbc, downclocking, etc. (default: true)");
-module_param_named(semaphores, i915.semaphores, int, 0400);
+module_param_named_unsafe(semaphores, i915.semaphores, int, 0400);
MODULE_PARM_DESC(semaphores,
"Use semaphores for inter-ring sync "
"(default: -1 (use per-chip defaults))");
-module_param_named(enable_rc6, i915.enable_rc6, int, 0400);
+module_param_named_unsafe(enable_rc6, i915.enable_rc6, int, 0400);
MODULE_PARM_DESC(enable_rc6,
"Enable power-saving render C-state 6. "
"Different stages can be selected via bitmask values "
@@ -79,7 +79,7 @@ MODULE_PARM_DESC(enable_rc6,
"For example, 3 would enable rc6 and deep rc6, and 7 would enable everything. "
"default: -1 (use per-chip default)");
-module_param_named(enable_fbc, i915.enable_fbc, int, 0600);
+module_param_named_unsafe(enable_fbc, i915.enable_fbc, int, 0600);
MODULE_PARM_DESC(enable_fbc,
"Enable frame buffer compression for power savings "
"(default: -1 (use per-chip default))");
@@ -113,7 +113,7 @@ MODULE_PARM_DESC(enable_hangcheck,
"WARNING: Disabling this can cause system wide hangs. "
"(default: true)");
-module_param_named(enable_ppgtt, i915.enable_ppgtt, int, 0400);
+module_param_named_unsafe(enable_ppgtt, i915.enable_ppgtt, int, 0400);
MODULE_PARM_DESC(enable_ppgtt,
"Override PPGTT usage. "
"(-1=auto [default], 0=disabled, 1=aliasing, 2=full)");
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 1d42dba6121..bd672948f2f 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -3587,7 +3587,7 @@ static void __used s8250_options(void)
#ifdef CONFIG_SERIAL_8250_RSA
__module_param_call(MODULE_PARAM_PREFIX, probe_rsa,
&param_array_ops, .arr = &__param_arr_probe_rsa,
- 0444, -1);
+ 0444, -1, 0);
#endif
}
#else
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
index 494f99e852d..b43f4752304 100644
--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -42,7 +42,7 @@ struct kernel_param;
* NOARG - the parameter allows for no argument (foo instead of foo=1)
*/
enum {
- KERNEL_PARAM_FL_NOARG = (1 << 0)
+ KERNEL_PARAM_OPS_FL_NOARG = (1 << 0)
};
struct kernel_param_ops {
@@ -56,11 +56,21 @@ struct kernel_param_ops {
void (*free)(void *arg);
};
+/*
+ * Flags available for kernel_param
+ *
+ * UNSAFE - the parameter is dangerous and setting it will taint the kernel
+ */
+enum {
+ KERNEL_PARAM_FL_UNSAFE = (1 << 0)
+};
+
struct kernel_param {
const char *name;
const struct kernel_param_ops *ops;
u16 perm;
- s16 level;
+ s8 level;
+ u8 flags;
union {
void *arg;
const struct kparam_string *str;
@@ -113,6 +123,12 @@ struct kparam_array
module_param_named(name, name, type, perm)
/**
+ * module_param_unsafe - same as module_param but taints kernel
+ */
+#define module_param_unsafe(name, type, perm) \
+ module_param_named_unsafe(name, name, type, perm)
+
+/**
* module_param_named - typesafe helper for a renamed module/cmdline parameter
* @name: a valid C identifier which is the parameter name.
* @value: the actual lvalue to alter.
@@ -129,6 +145,14 @@ struct kparam_array
__MODULE_PARM_TYPE(name, #type)
/**
+ * module_param_named_unsafe - same as module_param_named but taints kernel
+ */
+#define module_param_named_unsafe(name, value, type, perm) \
+ param_check_##type(name, &(value)); \
+ module_param_cb_unsafe(name, &param_ops_##type, &value, perm); \
+ __MODULE_PARM_TYPE(name, #type)
+
+/**
* module_param_cb - general callback for a module/cmdline parameter
* @name: a valid C identifier which is the parameter name.
* @ops: the set & get operations for this parameter.
@@ -137,7 +161,11 @@ struct kparam_array
* The ops can have NULL set or get functions.
*/
#define module_param_cb(name, ops, arg, perm) \
- __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, -1)
+ __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, -1, 0)
+
+#define module_param_cb_unsafe(name, ops, arg, perm) \
+ __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, -1, \
+ KERNEL_PARAM_FL_UNSAFE)
/**
* <level>_param_cb - general callback for a module/cmdline parameter
@@ -149,7 +177,7 @@ struct kparam_array
* The ops can have NULL set or get functions.
*/
#define __level_param_cb(name, ops, arg, perm, level) \
- __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, level)
+ __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, level, 0)
#define core_param_cb(name, ops, arg, perm) \
__level_param_cb(name, ops, arg, perm, 1)
@@ -184,22 +212,22 @@ struct kparam_array
/* This is the fundamental function for registering boot/module
parameters. */
-#define __module_param_call(prefix, name, ops, arg, perm, level) \
+#define __module_param_call(prefix, name, ops, arg, perm, level, flags) \
/* Default value instead of permissions? */ \
static const char __param_str_##name[] = prefix #name; \
static struct kernel_param __moduleparam_const __param_##name \
__used \
__attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \
= { __param_str_##name, ops, VERIFY_OCTAL_PERMISSIONS(perm), \
- level, { arg } }
+ level, flags, { arg } }
/* Obsolete - use module_param_cb() */
#define module_param_call(name, set, get, arg, perm) \
static struct kernel_param_ops __param_ops_##name = \
- { 0, (void *)set, (void *)get }; \
+ { .flags = 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)
+ (perm) + sizeof(__check_old_set_param(set))*0, -1, 0)
/* We don't get oldget: it's often a new-style param_get_uint, etc. */
static inline int
@@ -279,7 +307,7 @@ static inline void __kernel_param_unlock(void)
*/
#define core_param(name, var, type, perm) \
param_check_##type(name, &(var)); \
- __module_param_call("", name, &param_ops_##type, &var, perm, -1)
+ __module_param_call("", name, &param_ops_##type, &var, perm, -1, 0)
#endif /* !MODULE */
/**
@@ -297,7 +325,7 @@ static inline void __kernel_param_unlock(void)
= { len, string }; \
__module_param_call(MODULE_PARAM_PREFIX, name, \
&param_ops_string, \
- .str = &__param_string_##name, perm, -1); \
+ .str = &__param_string_##name, perm, -1, 0);\
__MODULE_PARM_TYPE(name, "string")
/**
@@ -444,7 +472,7 @@ extern int param_set_bint(const char *val, const struct kernel_param *kp);
__module_param_call(MODULE_PARAM_PREFIX, name, \
&param_array_ops, \
.arr = &__param_arr_##name, \
- perm, -1); \
+ perm, -1, 0); \
__MODULE_PARM_TYPE(name, "array of " #type)
extern struct kernel_param_ops param_array_ops;
diff --git a/init/Kconfig b/init/Kconfig
index b48917717ba..e25a82a291a 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1919,6 +1919,49 @@ config MODULE_SIG_HASH
default "sha384" if MODULE_SIG_SHA384
default "sha512" if MODULE_SIG_SHA512
+config MODULE_COMPRESS
+ bool "Compress modules on installation"
+ depends on MODULES
+ help
+ This option compresses the kernel modules when 'make
+ modules_install' is run.
+
+ The modules will be compressed either using gzip or xz depend on the
+ choice made in "Compression algorithm".
+
+ module-init-tools has support for gzip format while kmod handle gzip
+ and xz compressed modules.
+
+ When a kernel module is installed from outside of the main kernel
+ source and uses the Kbuild system for installing modules then that
+ kernel module will also be compressed when it is installed.
+
+ This option provides little benefit when the modules are to be used inside
+ an initrd or initramfs, it generally is more efficient to compress the whole
+ initrd or initramfs instead.
+
+ This is fully compatible with signed modules while the signed module is
+ compressed. module-init-tools or kmod handles decompression and provide to
+ other layer the uncompressed but signed payload.
+
+choice
+ prompt "Compression algorithm"
+ depends on MODULE_COMPRESS
+ default MODULE_COMPRESS_GZIP
+ help
+ This determines which sort of compression will be used during
+ 'make modules_install'.
+
+ GZIP (default) and XZ are supported.
+
+config MODULE_COMPRESS_GZIP
+ bool "GZIP"
+
+config MODULE_COMPRESS_XZ
+ bool "XZ"
+
+endchoice
+
endif # MODULES
config INIT_ALL_POSSIBLE
diff --git a/kernel/module.c b/kernel/module.c
index 03214bd288e..8a0dc91eddb 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -135,7 +135,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,
+ .flags = KERNEL_PARAM_OPS_FL_NOARG,
.set = param_set_bool_enable_only,
.get = param_get_bool,
};
diff --git a/kernel/params.c b/kernel/params.c
index 34f52702379..041b5899d5e 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -83,6 +83,15 @@ bool parameq(const char *a, const char *b)
return parameqn(a, b, strlen(a)+1);
}
+static void param_check_unsafe(const struct kernel_param *kp)
+{
+ if (kp->flags & KERNEL_PARAM_FL_UNSAFE) {
+ pr_warn("Setting dangerous option %s - tainting kernel\n",
+ kp->name);
+ add_taint(TAINT_USER, LOCKDEP_STILL_OK);
+ }
+}
+
static int parse_one(char *param,
char *val,
const char *doing,
@@ -104,11 +113,12 @@ static int parse_one(char *param,
return 0;
/* No one handled NULL, so do it here. */
if (!val &&
- !(params[i].ops->flags & KERNEL_PARAM_FL_NOARG))
+ !(params[i].ops->flags & KERNEL_PARAM_OPS_FL_NOARG))
return -EINVAL;
pr_debug("handling %s with %p\n", param,
params[i].ops->set);
mutex_lock(&param_lock);
+ param_check_unsafe(&params[i]);
err = params[i].ops->set(val, &params[i]);
mutex_unlock(&param_lock);
return err;
@@ -318,7 +328,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,
+ .flags = KERNEL_PARAM_OPS_FL_NOARG,
.set = param_set_bool,
.get = param_get_bool,
};
@@ -369,7 +379,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,
+ .flags = KERNEL_PARAM_OPS_FL_NOARG,
.set = param_set_bint,
.get = param_get_int,
};
@@ -552,6 +562,7 @@ static ssize_t param_attr_store(struct module_attribute *mattr,
return -EPERM;
mutex_lock(&param_lock);
+ param_check_unsafe(attribute->param);
err = attribute->param->ops->set(buf, attribute->param);
mutex_unlock(&param_lock);
if (!err)
diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst
index 95ec7b35e8b..e48a4e9d886 100644
--- a/scripts/Makefile.modinst
+++ b/scripts/Makefile.modinst
@@ -18,7 +18,12 @@ __modinst: $(modules)
# Don't stop modules_install if we can't sign external modules.
quiet_cmd_modules_install = INSTALL $@
- cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) ; $(mod_sign_cmd) $(2)/$(notdir $@) $(patsubst %,|| true,$(KBUILD_EXTMOD))
+ cmd_modules_install = \
+ mkdir -p $(2) ; \
+ cp $@ $(2) ; \
+ $(mod_strip_cmd) $(2)/$(notdir $@) ; \
+ $(mod_sign_cmd) $(2)/$(notdir $@) $(patsubst %,|| true,$(KBUILD_EXTMOD)) ; \
+ $(mod_compress_cmd) $(2)/$(notdir $@)
# Modules built outside the kernel source tree go into extra by default
INSTALL_MOD_DIR ?= extra
diff --git a/scripts/Makefile.modsign b/scripts/Makefile.modsign
index abfda626dba..b6ac7084da7 100644
--- a/scripts/Makefile.modsign
+++ b/scripts/Makefile.modsign
@@ -7,7 +7,7 @@ __modsign:
include scripts/Kbuild.include
-__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
+__modules := $(sort $(shell grep -h '\.ko$$' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o)))
PHONY += $(modules)
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 091d90573b6..3b405c726ec 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -24,9 +24,9 @@
#include "../../include/linux/export.h"
/* Are we using CONFIG_MODVERSIONS? */
-int modversions = 0;
+static int modversions = 0;
/* Warn about undefined symbols? (do so if we have vmlinux) */
-int have_vmlinux = 0;
+static int have_vmlinux = 0;
/* Is CONFIG_MODULE_SRCVERSION_ALL set? */
static int all_versions = 0;
/* If we are modposting external module set to 1 */
@@ -229,7 +229,7 @@ static struct symbol *find_symbol(const char *name)
return NULL;
}
-static struct {
+static const struct {
const char *str;
enum export export;
} export_list[] = {
@@ -805,7 +805,7 @@ static int match(const char *sym, const char * const pat[])
}
/* sections that we do not want to do full section mismatch check on */
-static const char *section_white_list[] =
+static const char *const section_white_list[] =
{
".comment*",
".debug*",
@@ -882,17 +882,18 @@ static void check_section(const char *modname, struct elf_info *elf,
#define MEM_EXIT_SECTIONS ".memexit.*"
/* init data sections */
-static const char *init_data_sections[] = { ALL_INIT_DATA_SECTIONS, NULL };
+static const char *const init_data_sections[] =
+ { ALL_INIT_DATA_SECTIONS, NULL };
/* all init sections */
-static const char *init_sections[] = { ALL_INIT_SECTIONS, NULL };
+static const char *const init_sections[] = { ALL_INIT_SECTIONS, NULL };
/* All init and exit sections (code + data) */
-static const char *init_exit_sections[] =
+static const char *const init_exit_sections[] =
{ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL };
/* data section */
-static const char *data_sections[] = { DATA_SECTIONS, NULL };
+static const char *const data_sections[] = { DATA_SECTIONS, NULL };
/* symbols in .data that may refer to init/exit sections */
@@ -906,8 +907,8 @@ static const char *data_sections[] = { DATA_SECTIONS, NULL };
"*_probe_one", \
"*_console"
-static const char *head_sections[] = { ".head.text*", NULL };
-static const char *linker_symbols[] =
+static const char *const head_sections[] = { ".head.text*", NULL };
+static const char *const linker_symbols[] =
{ "__init_begin", "_sinittext", "_einittext", NULL };
enum mismatch {
@@ -929,7 +930,7 @@ struct sectioncheck {
const char *symbol_white_list[20];
};
-const struct sectioncheck sectioncheck[] = {
+static const struct sectioncheck sectioncheck[] = {
/* Do not reference init/exit code/data from
* normal code and data
*/
@@ -2211,7 +2212,7 @@ int main(int argc, char **argv)
err = 0;
for (mod = modules; mod; mod = mod->next) {
- char fname[strlen(mod->name) + 10];
+ char fname[PATH_MAX];
if (mod->skip)
continue;
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 99810009333..65ca451a764 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -668,7 +668,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,
+ .flags = KERNEL_PARAM_OPS_FL_NOARG,
.set = param_set_aabool,
.get = param_get_aabool
};
@@ -685,7 +685,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,
+ .flags = KERNEL_PARAM_OPS_FL_NOARG,
.set = param_set_aalockpolicy,
.get = param_get_aalockpolicy
};