diff --git a/config/Config-build.in b/config/Config-build.in
index a082a5e0e2..72076d0648 100644
--- a/config/Config-build.in
+++ b/config/Config-build.in
@@ -151,6 +151,35 @@ menu "Global build settings"
 		  image.  Note that this might make the kernel incompatible with any kernel
 		  modules that were not selected at the time the kernel image was created.
 
+	choice
+		prompt "Kernel module stripping"
+		default KERNEL_MODULE_STRIP_ALL
+		help
+		  If and how modules should be stripped upon install.  Modules
+		  in the Linux build tree remain unchanged.
+
+		config MODULE_STRIP_NONE
+			bool "strip none"
+			help
+			  Will install modules exactly as they are built in the
+			  tree, including any debug symbols if enabled in the
+			  Kernel Hacking menuconfig menu.
+
+		config MODULE_STRIP_UNNEEDED
+			bool "strip unneeded"
+			help
+			  Strips all unneeded symbols from modules as they are
+			  installed.
+
+		config KERNEL_MODULE_STRIP_ALL
+			bool "strip all"
+			help
+			  Further reduces size of kernel modules by stripping
+			  all symbols, including relocations, and removing
+			  customary strings such as author, version, parameter
+			  descriptions, etc.
+	endchoice
+
 	config USE_MKLIBS
 		bool "Strip unnecessary functions from libraries"
 		help
diff --git a/include/kernel.mk b/include/kernel.mk
index 62a8e99e2d..251ac1c94c 100644
--- a/include/kernel.mk
+++ b/include/kernel.mk
@@ -122,6 +122,18 @@ ifdef CONFIG_USE_SPARSE
   KERNEL_MAKEOPTS += C=1 CHECK=$(STAGING_DIR_HOST)/bin/sparse
 endif
 
+# Define command for copying kernel modules.
+ifeq ($(CONFIG_MODULE_STRIP_NONE),y)
+  MODULE_COPY := $(CP) -L
+else
+  MODULE_COPY = $(KERNEL_CROSS)objcopy
+  ifeq ($(CONFIG_MODULE_STRIP_UNNEEDED),y)
+    MODULE_COPY += --strip-unneeded
+  else # CONFIG_MODULE_STRIP_ALL
+    MODULE_COPY += --strip-all
+  endif
+endif
+
 PKG_EXTMOD_SUBDIRS ?= .
 
 define populate_module_symvers
@@ -229,8 +241,9 @@ $(call KernelPackage/$(1)/config)
 			if grep -q "$$$$$$$${mod##$(LINUX_DIR)/}" "$(LINUX_DIR)/modules.builtin"; then \
 				echo "NOTICE: module '$$$$$$$$mod' is built-in."; \
 			elif [ -e $$$$$$$$mod ]; then \
-				mkdir -p $$(1)/$(MODULES_SUBDIR) ; \
-				$(CP) -L $$$$$$$$mod $$(1)/$(MODULES_SUBDIR)/ ; \
+				mkdir -p $$(1)/$(MODULES_SUBDIR); \
+				mod_name=`basename $$$$$$$$mod`; \
+				$(MODULE_COPY) $$$$$$$$mod $$(1)/$(MODULES_SUBDIR)/$$$$$$$$mod_name; \
 			else \
 				echo "ERROR: module '$$$$$$$$mod' is missing." >&2; \
 				exit 1; \
diff --git a/target/linux/generic/config-4.14 b/target/linux/generic/config-4.14
index 97207cf2eb..8a12b422cb 100644
--- a/target/linux/generic/config-4.14
+++ b/target/linux/generic/config-4.14
@@ -2674,7 +2674,6 @@ CONFIG_MODULES=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 # CONFIG_MODULE_SIG is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_MODULE_STRIPPED=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MOST is not set
diff --git a/target/linux/generic/config-4.9 b/target/linux/generic/config-4.9
index 979028f04a..18cf72e75e 100644
--- a/target/linux/generic/config-4.9
+++ b/target/linux/generic/config-4.9
@@ -2502,7 +2502,6 @@ CONFIG_MODULES=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 # CONFIG_MODULE_SIG is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_MODULE_STRIPPED=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MOST is not set
diff --git a/target/linux/generic/hack-4.14/204-module_strip.patch b/target/linux/generic/hack-4.14/204-module_strip.patch
index db65062fcf..6ddc6a7312 100644
--- a/target/linux/generic/hack-4.14/204-module_strip.patch
+++ b/target/linux/generic/hack-4.14/204-module_strip.patch
@@ -34,7 +34,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 +#define MODULE_DESCRIPTION(_description) MODULE_INFO_STRIP(description, _description)
  
 -#ifdef MODULE
-+#if defined(MODULE) && !defined(CONFIG_MODULE_STRIPPED)
++#if defined(MODULE) && !defined(CONFIG_MODULE_STRIP_ALL)
  /* Creates an alias so file2alias.c can find device table. */
  #define MODULE_DEVICE_TABLE(type, name)					\
  extern typeof(name) __mod_##type##__##name##_device_table		\
@@ -44,7 +44,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  #if defined(MODULE) || !defined(CONFIG_SYSFS)
 -#define MODULE_VERSION(_version) MODULE_INFO(version, _version)
 +#define MODULE_VERSION(_version) MODULE_INFO_STRIP(version, _version)
-+#elif defined(CONFIG_MODULE_STRIPPED)
++#elif defined(CONFIG_MODULE_STRIP_ALL)
 +#define MODULE_VERSION(_version) __MODULE_INFO_DISABLED(version)
  #else
  #define MODULE_VERSION(_version)					\
@@ -68,7 +68,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 +#define __MODULE_INFO_DISABLED(name)					  \
 +  struct __UNIQUE_ID(name) {}
 +
-+#ifdef CONFIG_MODULE_STRIPPED
++#ifdef CONFIG_MODULE_STRIP_ALL
 +#define __MODULE_INFO_STRIP(tag, name, info) __MODULE_INFO_DISABLED(name)
 +#else
 +#define __MODULE_INFO_STRIP(tag, name, info) __MODULE_INFO(tag, name, info)
@@ -102,7 +102,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  
  	  If unsure, or if you need to build out-of-tree modules, say N.
  
-+config MODULE_STRIPPED
++config MODULE_STRIP_ALL
 +	bool "Reduce module size"
 +	depends on MODULES
 +	help
@@ -121,7 +121,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 -	const char *modmagic = get_modinfo(info, "vermagic");
  	int err;
  
-+#ifndef CONFIG_MODULE_STRIPPED
++#ifndef CONFIG_MODULE_STRIP_ALL
 +	const char *modmagic = get_modinfo(info, "vermagic");
 +
  	if (flags & MODULE_INIT_IGNORE_VERMAGIC)
@@ -141,7 +141,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  		symname = remove_dot(info.strtab + sym->st_name);
  
  		handle_modversions(mod, &info, sym, symname);
-+#ifndef CONFIG_MODULE_STRIPPED
++#ifndef CONFIG_MODULE_STRIP_ALL
  		handle_moddevtable(mod, &info, sym, symname);
 +#endif
  	}
@@ -151,7 +151,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  	buf_printf(b, "#include <linux/vermagic.h>\n");
  	buf_printf(b, "#include <linux/compiler.h>\n");
  	buf_printf(b, "\n");
-+#ifndef CONFIG_MODULE_STRIPPED
++#ifndef CONFIG_MODULE_STRIP_ALL
  	buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n");
  	buf_printf(b, "MODULE_INFO(name, KBUILD_MODNAME);\n");
 +#endif
@@ -162,7 +162,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  
  static void add_intree_flag(struct buffer *b, int is_intree)
  {
-+#ifndef CONFIG_MODULE_STRIPPED
++#ifndef CONFIG_MODULE_STRIP_ALL
  	if (is_intree)
  		buf_printf(b, "\nMODULE_INFO(intree, \"Y\");\n");
 +#endif
@@ -173,7 +173,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  
  static void add_staging_flag(struct buffer *b, const char *name)
  {
-+#ifndef CONFIG_MODULE_STRIPPED
++#ifndef CONFIG_MODULE_STRIP_ALL
  	static const char *staging_dir = "drivers/staging";
  
  	if (strncmp(staging_dir, name, strlen(staging_dir)) == 0)
@@ -186,7 +186,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  
  static void add_srcversion(struct buffer *b, struct module *mod)
  {
-+#ifndef CONFIG_MODULE_STRIPPED
++#ifndef CONFIG_MODULE_STRIP_ALL
  	if (mod->srcversion[0]) {
  		buf_printf(b, "\n");
  		buf_printf(b, "MODULE_INFO(srcversion, \"%s\");\n",
@@ -200,7 +200,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  		add_staging_flag(&buf, mod->name);
  		err |= add_versions(&buf, mod);
  		add_depends(&buf, mod, modules);
-+#ifndef CONFIG_MODULE_STRIPPED
++#ifndef CONFIG_MODULE_STRIP_ALL
  		add_moddevtable(&buf, mod);
 +#endif
  		add_srcversion(&buf, mod);
diff --git a/target/linux/generic/hack-4.9/204-module_strip.patch b/target/linux/generic/hack-4.9/204-module_strip.patch
index c6484a8f92..68707422a3 100644
--- a/target/linux/generic/hack-4.9/204-module_strip.patch
+++ b/target/linux/generic/hack-4.9/204-module_strip.patch
@@ -34,7 +34,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 +#define MODULE_DESCRIPTION(_description) MODULE_INFO_STRIP(description, _description)
  
 -#ifdef MODULE
-+#if defined(MODULE) && !defined(CONFIG_MODULE_STRIPPED)
++#if defined(MODULE) && !defined(CONFIG_MODULE_STRIP_ALL)
  /* Creates an alias so file2alias.c can find device table. */
  #define MODULE_DEVICE_TABLE(type, name)					\
  extern const typeof(name) __mod_##type##__##name##_device_table		\
@@ -44,7 +44,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  #if defined(MODULE) || !defined(CONFIG_SYSFS)
 -#define MODULE_VERSION(_version) MODULE_INFO(version, _version)
 +#define MODULE_VERSION(_version) MODULE_INFO_STRIP(version, _version)
-+#elif defined(CONFIG_MODULE_STRIPPED)
++#elif defined(CONFIG_MODULE_STRIP_ALL)
 +#define MODULE_VERSION(_version) __MODULE_INFO_DISABLED(version)
  #else
  #define MODULE_VERSION(_version)					\
@@ -68,7 +68,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 +#define __MODULE_INFO_DISABLED(name)					  \
 +  struct __UNIQUE_ID(name) {}
 +
-+#ifdef CONFIG_MODULE_STRIPPED
++#ifdef CONFIG_MODULE_STRIP_ALL
 +#define __MODULE_INFO_STRIP(tag, name, info) __MODULE_INFO_DISABLED(name)
 +#else
 +#define __MODULE_INFO_STRIP(tag, name, info) __MODULE_INFO(tag, name, info)
@@ -102,7 +102,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  
  	  If unsure, or if you need to build out-of-tree modules, say N.
  
-+config MODULE_STRIPPED
++config MODULE_STRIP_ALL
 +	bool "Reduce module size"
 +	depends on MODULES
 +	help
@@ -121,7 +121,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 -	const char *modmagic = get_modinfo(info, "vermagic");
  	int err;
  
-+#ifndef CONFIG_MODULE_STRIPPED
++#ifndef CONFIG_MODULE_STRIP_ALL
 +	const char *modmagic = get_modinfo(info, "vermagic");
 +
  	if (flags & MODULE_INIT_IGNORE_VERMAGIC)
@@ -141,7 +141,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  		symname = remove_dot(info.strtab + sym->st_name);
  
  		handle_modversions(mod, &info, sym, symname);
-+#ifndef CONFIG_MODULE_STRIPPED
++#ifndef CONFIG_MODULE_STRIP_ALL
  		handle_moddevtable(mod, &info, sym, symname);
 +#endif
  	}
@@ -151,7 +151,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  	buf_printf(b, "#include <linux/vermagic.h>\n");
  	buf_printf(b, "#include <linux/compiler.h>\n");
  	buf_printf(b, "\n");
-+#ifndef CONFIG_MODULE_STRIPPED
++#ifndef CONFIG_MODULE_STRIP_ALL
  	buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n");
 +#endif
  	buf_printf(b, "\n");
@@ -161,7 +161,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  
  static void add_intree_flag(struct buffer *b, int is_intree)
  {
-+#ifndef CONFIG_MODULE_STRIPPED
++#ifndef CONFIG_MODULE_STRIP_ALL
  	if (is_intree)
  		buf_printf(b, "\nMODULE_INFO(intree, \"Y\");\n");
 +#endif
@@ -170,7 +170,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  /* Cannot check for assembler */
  static void add_retpoline(struct buffer *b)
  {
-+#ifndef CONFIG_MODULE_STRIPPED
++#ifndef CONFIG_MODULE_STRIP_ALL
  	buf_printf(b, "\n#ifdef RETPOLINE\n");
  	buf_printf(b, "MODULE_INFO(retpoline, \"Y\");\n");
  	buf_printf(b, "#endif\n");
@@ -179,7 +179,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  
  static void add_staging_flag(struct buffer *b, const char *name)
  {
-+#ifndef CONFIG_MODULE_STRIPPED
++#ifndef CONFIG_MODULE_STRIP_ALL
  	static const char *staging_dir = "drivers/staging";
  
  	if (strncmp(staging_dir, name, strlen(staging_dir)) == 0)
@@ -192,7 +192,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  
  static void add_srcversion(struct buffer *b, struct module *mod)
  {
-+#ifndef CONFIG_MODULE_STRIPPED
++#ifndef CONFIG_MODULE_STRIP_ALL
  	if (mod->srcversion[0]) {
  		buf_printf(b, "\n");
  		buf_printf(b, "MODULE_INFO(srcversion, \"%s\");\n",
@@ -206,7 +206,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  		add_staging_flag(&buf, mod->name);
  		err |= add_versions(&buf, mod);
  		add_depends(&buf, mod, modules);
-+#ifndef CONFIG_MODULE_STRIPPED
++#ifndef CONFIG_MODULE_STRIP_ALL
  		add_moddevtable(&buf, mod);
 +#endif
  		add_srcversion(&buf, mod);
