diff --git a/Config.in b/Config.in
index 9879c7d9c099b5bb0418f3ee4867164be31e6db9..40764790219127af606449d8a861722899bc1300 100644
--- a/Config.in
+++ b/Config.in
@@ -134,6 +134,14 @@ config USE_MKLIBS
 	  Note that this will make the system libraries incompatible with most of the packages
 	  that are not selected during the build process
 
+config STRIP_KERNEL_EXPORTS
+	depends LINUX_2_6
+	bool "Strip unnecessary exports from the kernel image"
+	help
+	  Reduces kernel size by stripping unused kernel exports from the kernel 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
+
 comment "Package build options"
 
 config DEBUG
diff --git a/include/kernel-build.mk b/include/kernel-build.mk
index d48f8b9f53c8255d98767a7f92eadf97a0f7a1f9..e3e446ba584c17abb6e7d713fc22b413a28d873d 100644
--- a/include/kernel-build.mk
+++ b/include/kernel-build.mk
@@ -54,6 +54,28 @@ define BuildKernel
 	$(Kernel/Prepare)
 	touch $$@
 
+  $(KERNEL_BUILD_DIR)/symtab.txt: FORCE
+	find $(LINUX_DIR) $(STAGING_DIR_ROOT)/lib/modules -name \*.ko | \
+		xargs $(TARGET_CROSS)nm | \
+		awk '$$$$1 == "U" { print $$$$2 } ' | \
+		sort -u > $$@
+
+  $(KERNEL_BUILD_DIR)/symtab.h: $(KERNEL_BUILD_DIR)/symtab.txt
+	( \
+		echo '#define SYMTAB_KEEP \'; \
+		cat $(KERNEL_BUILD_DIR)/symtab.txt | \
+			awk '{print "*(__ksymtab." $$$$1 ") \\" }'; \
+		echo; \
+		echo '#define SYMTAB_KEEP_GPL \'; \
+		cat $(KERNEL_BUILD_DIR)/symtab.txt | \
+			awk '{print "*(__ksymtab_gpl." $$$$1 ") \\" }'; \
+		echo; \
+		echo '#define SYMTAB_KEEP_STR \'; \
+		cat $(KERNEL_BUILD_DIR)/symtab.txt | \
+			awk '{print "*(__ksymtab_strings." $$$$1 ") \\" }'; \
+		echo; \
+	) > $$@
+
   $(STAMP_CONFIGURED): $(STAMP_PREPARED) $(LINUX_CONFIG) $(GENERIC_LINUX_CONFIG) $(TOPDIR)/.config
 	$(Kernel/Configure)
 	touch $$@
@@ -62,7 +84,7 @@ define BuildKernel
 	$(Kernel/CompileModules)
 	touch $$@
 
-  $(LINUX_DIR)/.image: $(STAMP_CONFIGURED) FORCE
+  $(LINUX_DIR)/.image: $(STAMP_CONFIGURED) $(if $(CONFIG_STRIP_KERNEL_EXPORTS),$(KERNEL_BUILD_DIR)/symtab.h) FORCE
 	$(Kernel/CompileImage)
 	touch $$@
 	
diff --git a/include/kernel-defaults.mk b/include/kernel-defaults.mk
index f2055535871f98393d773626f8aed8612253bafa..0ba1e056a69a30c5c626e66d6e66d6190aeaac8b 100644
--- a/include/kernel-defaults.mk
+++ b/include/kernel-defaults.mk
@@ -22,6 +22,11 @@ KERNEL_MAKEOPTS := -C $(LINUX_DIR) \
 	KBUILD_HAVE_NLS=no \
 	CONFIG_SHELL="$(BASH)"
 
+ifdef CONFIG_STRIP_KERNEL_EXPORTS
+  KERNEL_MAKEOPTS += \
+	EXTRA_LDSFLAGS="-I$(KERNEL_BUILD_DIR) -include symtab.h"
+endif
+
 INITRAMFS_EXTRA_FILES ?= $(GENERIC_PLATFORM_DIR)/image/initramfs-base-files.txt
 
 ifneq (,$(KERNEL_CC))
diff --git a/target/linux/generic-2.6/patches-2.6.28/027-module_exports.patch b/target/linux/generic-2.6/patches-2.6.28/027-module_exports.patch
new file mode 100644
index 0000000000000000000000000000000000000000..2a4483262d24d2f05adc47a3a5203ad26ad0412c
--- /dev/null
+++ b/target/linux/generic-2.6/patches-2.6.28/027-module_exports.patch
@@ -0,0 +1,117 @@
+--- a/Makefile
++++ b/Makefile
+@@ -963,7 +963,7 @@ prepare: prepare0
+ # Leave this as default for preprocessing vmlinux.lds.S, which is now
+ # done in arch/$(ARCH)/kernel/Makefile
+ 
+-export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
++export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH) $(EXTRA_LDSFLAGS)
+ 
+ # The asm symlink changes when $(ARCH) changes.
+ # Detect this and ask user to run make mrproper
+--- a/include/asm-generic/vmlinux.lds.h
++++ b/include/asm-generic/vmlinux.lds.h
+@@ -2,6 +2,18 @@
+ #define LOAD_OFFSET 0
+ #endif
+ 
++#ifndef SYMTAB_KEEP_STR
++#define SYMTAB_KEEP_STR *(__ksymtab_strings.*)
++#endif
++
++#ifndef SYMTAB_KEEP
++#define SYMTAB_KEEP *(__ksymtab.*)
++#endif
++
++#ifndef SYMTAB_KEEP_GPL
++#define SYMTAB_KEEP_GPL *(__ksymtab_gpl.*)
++#endif
++
+ #ifndef VMLINUX_SYMBOL
+ #define VMLINUX_SYMBOL(_sym_) _sym_
+ #endif
+@@ -124,35 +136,35 @@
+ 	/* Kernel symbol table: Normal symbols */			\
+ 	__ksymtab         : AT(ADDR(__ksymtab) - LOAD_OFFSET) {		\
+ 		VMLINUX_SYMBOL(__start___ksymtab) = .;			\
+-		*(__ksymtab)						\
++		SYMTAB_KEEP						\
+ 		VMLINUX_SYMBOL(__stop___ksymtab) = .;			\
+ 	}								\
+ 									\
+ 	/* Kernel symbol table: GPL-only symbols */			\
+ 	__ksymtab_gpl     : AT(ADDR(__ksymtab_gpl) - LOAD_OFFSET) {	\
+ 		VMLINUX_SYMBOL(__start___ksymtab_gpl) = .;		\
+-		*(__ksymtab_gpl)					\
++		SYMTAB_KEEP_GPL						\
+ 		VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .;		\
+ 	}								\
+ 									\
+ 	/* Kernel symbol table: Normal unused symbols */		\
+ 	__ksymtab_unused  : AT(ADDR(__ksymtab_unused) - LOAD_OFFSET) {	\
+ 		VMLINUX_SYMBOL(__start___ksymtab_unused) = .;		\
+-		*(__ksymtab_unused)					\
++		*(__ksymtab_unused.*)					\
+ 		VMLINUX_SYMBOL(__stop___ksymtab_unused) = .;		\
+ 	}								\
+ 									\
+ 	/* Kernel symbol table: GPL-only unused symbols */		\
+ 	__ksymtab_unused_gpl : AT(ADDR(__ksymtab_unused_gpl) - LOAD_OFFSET) { \
+ 		VMLINUX_SYMBOL(__start___ksymtab_unused_gpl) = .;	\
+-		*(__ksymtab_unused_gpl)					\
++		*(__ksymtab_unused_gpl.*)				\
+ 		VMLINUX_SYMBOL(__stop___ksymtab_unused_gpl) = .;	\
+ 	}								\
+ 									\
+ 	/* Kernel symbol table: GPL-future-only symbols */		\
+ 	__ksymtab_gpl_future : AT(ADDR(__ksymtab_gpl_future) - LOAD_OFFSET) { \
+ 		VMLINUX_SYMBOL(__start___ksymtab_gpl_future) = .;	\
+-		*(__ksymtab_gpl_future)					\
++		*(__ksymtab_gpl_future.*)				\
+ 		VMLINUX_SYMBOL(__stop___ksymtab_gpl_future) = .;	\
+ 	}								\
+ 									\
+@@ -193,7 +205,13 @@
+ 									\
+ 	/* Kernel symbol table: strings */				\
+         __ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) {	\
+-		*(__ksymtab_strings)					\
++		SYMTAB_KEEP_STR						\
++	}								\
++									\
++	/DISCARD/ : {							\
++		*(__ksymtab.*)						\
++		*(__ksymtab_gpl.*)					\
++		*(__ksymtab_strings.*)					\
+ 	}								\
+ 									\
+ 	/* __*init sections */						\
+--- a/include/linux/module.h
++++ b/include/linux/module.h
+@@ -187,16 +187,24 @@ void *__symbol_get_gpl(const char *symbo
+ #define __CRC_SYMBOL(sym, sec)
+ #endif
+ 
++#ifdef MODULE
++#define __EXPORT_SUFFIX(sym)
++#else
++#define __EXPORT_SUFFIX(sym) "." #sym
++#endif
++
+ /* For every exported symbol, place a struct in the __ksymtab section */
+ #define __EXPORT_SYMBOL(sym, sec)				\
+ 	extern typeof(sym) sym;					\
+ 	__CRC_SYMBOL(sym, sec)					\
+ 	static const char __kstrtab_##sym[]			\
+-	__attribute__((section("__ksymtab_strings"), aligned(1))) \
++	__attribute__((section("__ksymtab_strings"		\
++	  __EXPORT_SUFFIX(sym)), aligned(1)))			\
+ 	= MODULE_SYMBOL_PREFIX #sym;                    	\
+ 	static const struct kernel_symbol __ksymtab_##sym	\
+ 	__used							\
+-	__attribute__((section("__ksymtab" sec), unused))	\
++	__attribute__((section("__ksymtab" sec			\
++	  __EXPORT_SUFFIX(sym)), unused))			\
+ 	= { (unsigned long)&sym, __kstrtab_##sym }
+ 
+ #define EXPORT_SYMBOL(sym)					\
diff --git a/target/linux/generic-2.6/patches-2.6.30/028-module_exports.patch b/target/linux/generic-2.6/patches-2.6.30/028-module_exports.patch
new file mode 100644
index 0000000000000000000000000000000000000000..ec037b30e7af105fe62f6e0d6f16db30d0429faa
--- /dev/null
+++ b/target/linux/generic-2.6/patches-2.6.30/028-module_exports.patch
@@ -0,0 +1,117 @@
+--- a/include/asm-generic/vmlinux.lds.h
++++ b/include/asm-generic/vmlinux.lds.h
+@@ -4,6 +4,18 @@
+ #define LOAD_OFFSET 0
+ #endif
+ 
++#ifndef SYMTAB_KEEP_STR
++#define SYMTAB_KEEP_STR *(__ksymtab_strings.*)
++#endif
++
++#ifndef SYMTAB_KEEP
++#define SYMTAB_KEEP *(__ksymtab.*)
++#endif
++
++#ifndef SYMTAB_KEEP_GPL
++#define SYMTAB_KEEP_GPL *(__ksymtab_gpl.*)
++#endif
++
+ #ifndef VMLINUX_SYMBOL
+ #define VMLINUX_SYMBOL(_sym_) _sym_
+ #endif
+@@ -176,35 +188,35 @@
+ 	/* Kernel symbol table: Normal symbols */			\
+ 	__ksymtab         : AT(ADDR(__ksymtab) - LOAD_OFFSET) {		\
+ 		VMLINUX_SYMBOL(__start___ksymtab) = .;			\
+-		*(__ksymtab)						\
++		SYMTAB_KEEP						\
+ 		VMLINUX_SYMBOL(__stop___ksymtab) = .;			\
+ 	}								\
+ 									\
+ 	/* Kernel symbol table: GPL-only symbols */			\
+ 	__ksymtab_gpl     : AT(ADDR(__ksymtab_gpl) - LOAD_OFFSET) {	\
+ 		VMLINUX_SYMBOL(__start___ksymtab_gpl) = .;		\
+-		*(__ksymtab_gpl)					\
++		SYMTAB_KEEP_GPL						\
+ 		VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .;		\
+ 	}								\
+ 									\
+ 	/* Kernel symbol table: Normal unused symbols */		\
+ 	__ksymtab_unused  : AT(ADDR(__ksymtab_unused) - LOAD_OFFSET) {	\
+ 		VMLINUX_SYMBOL(__start___ksymtab_unused) = .;		\
+-		*(__ksymtab_unused)					\
++		*(__ksymtab_unused.*)					\
+ 		VMLINUX_SYMBOL(__stop___ksymtab_unused) = .;		\
+ 	}								\
+ 									\
+ 	/* Kernel symbol table: GPL-only unused symbols */		\
+ 	__ksymtab_unused_gpl : AT(ADDR(__ksymtab_unused_gpl) - LOAD_OFFSET) { \
+ 		VMLINUX_SYMBOL(__start___ksymtab_unused_gpl) = .;	\
+-		*(__ksymtab_unused_gpl)					\
++		*(__ksymtab_unused_gpl.*)				\
+ 		VMLINUX_SYMBOL(__stop___ksymtab_unused_gpl) = .;	\
+ 	}								\
+ 									\
+ 	/* Kernel symbol table: GPL-future-only symbols */		\
+ 	__ksymtab_gpl_future : AT(ADDR(__ksymtab_gpl_future) - LOAD_OFFSET) { \
+ 		VMLINUX_SYMBOL(__start___ksymtab_gpl_future) = .;	\
+-		*(__ksymtab_gpl_future)					\
++		*(__ksymtab_gpl_future.*)				\
+ 		VMLINUX_SYMBOL(__stop___ksymtab_gpl_future) = .;	\
+ 	}								\
+ 									\
+@@ -245,7 +257,13 @@
+ 									\
+ 	/* Kernel symbol table: strings */				\
+         __ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) {	\
+-		*(__ksymtab_strings)					\
++		SYMTAB_KEEP_STR						\
++	}								\
++									\
++	/DISCARD/ : {							\
++		*(__ksymtab.*)						\
++		*(__ksymtab_gpl.*)					\
++		*(__ksymtab_strings.*)					\
+ 	}								\
+ 									\
+ 	/* __*init sections */						\
+--- a/include/linux/module.h
++++ b/include/linux/module.h
+@@ -187,16 +187,24 @@ void *__symbol_get_gpl(const char *symbo
+ #define __CRC_SYMBOL(sym, sec)
+ #endif
+ 
++#ifdef MODULE
++#define __EXPORT_SUFFIX(sym)
++#else
++#define __EXPORT_SUFFIX(sym) "." #sym
++#endif
++
+ /* For every exported symbol, place a struct in the __ksymtab section */
+ #define __EXPORT_SYMBOL(sym, sec)				\
+ 	extern typeof(sym) sym;					\
+ 	__CRC_SYMBOL(sym, sec)					\
+ 	static const char __kstrtab_##sym[]			\
+-	__attribute__((section("__ksymtab_strings"), aligned(1))) \
++	__attribute__((section("__ksymtab_strings"		\
++	  __EXPORT_SUFFIX(sym)), aligned(1)))			\
+ 	= MODULE_SYMBOL_PREFIX #sym;                    	\
+ 	static const struct kernel_symbol __ksymtab_##sym	\
+ 	__used							\
+-	__attribute__((section("__ksymtab" sec), unused))	\
++	__attribute__((section("__ksymtab" sec			\
++	  __EXPORT_SUFFIX(sym)), unused))			\
+ 	= { (unsigned long)&sym, __kstrtab_##sym }
+ 
+ #define EXPORT_SYMBOL(sym)					\
+--- a/Makefile
++++ b/Makefile
+@@ -994,7 +994,7 @@ prepare: prepare0
+ # Leave this as default for preprocessing vmlinux.lds.S, which is now
+ # done in arch/$(ARCH)/kernel/Makefile
+ 
+-export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
++export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH) $(EXTRA_LDSFLAGS)
+ 
+ # The asm symlink changes when $(ARCH) changes.
+ # Detect this and ask user to run make mrproper