diff --git a/help.c b/help.c
index c9ae57e..ec905df 100755
--- a/help.c
+++ b/help.c
@@ -4495,7 +4495,7 @@ NULL
 char *help_mod[] = {
 "mod",
 "module information and loading of symbols and debugging data",
-"-s module [objfile] | -d module | -S [directory] | -D | -r | -R | -o | -g",
+"-s module [objfile] | -d module | -S [directory] | -D | -T | -t | -r | -R | -o | -g",
 "  With no arguments, this command displays basic information of the currently",
 "  installed modules, consisting of the module address, name, size, the",
 "  object file name (if known), and whether the module was compiled with",
@@ -4547,6 +4547,10 @@ char *help_mod[] = {
 "                       argument is appended, then the search will be restricted",
 "                       to that directory.",
 "                   -D  Deletes the symbolic and debugging data of all modules.",
+"                   -T  Report modules that are \"tainted\" and display their",
+"		       symbolic representation (for kernels with the tnts[]",
+"		       array only).",
+"                   -t  Same as the above, but will display in hexadecimal.",
 "                   -r  Passes the -readnow flag to the embedded gdb module,",
 "                       which will override the two-stage strategy that it uses",
 "                       for reading symbol tables from module object files.",
@@ -4557,6 +4561,9 @@ char *help_mod[] = {
 "                       start and end addresses to its symbol list.",
 "                   -o  Load module symbols with old mechanism.",
 " ",
+"  Where the -T (or -t) is used, the the relevant kernel sources should be",
+"  consulted for the meaning of either the letter(s) or hexadecimal bit-value(s).",
+" ",
 "  If the %s session was invoked with the \"--mod <directory>\" option, or",
 "  a CRASH_MODULE_PATH environment variable exists, then /lib/modules/<release>",
 "  will be overridden as the default directory tree that is searched for module",
@@ -4673,6 +4680,20 @@ char *help_mod[] = {
 "    c806e000  autofs       9316  (not loaded)",
 "    c8072000  nfsd       151896  (not loaded)",
 "    c80a1000  mdacon       3556  (not loaded)",
+" ",
+"  Display modules that are \"tainted\" with their symbolic representation:",
+" ",
+"    %s> mod -T",
+"     NAME                 TAINT",
+"     dm_mod               G",
+"     scsi_tgt             G",
+"     serio_raw            G",
+"     dm_log               G",
+"     ata_generic          G",
+"     qla2xxx              P(U)",
+"     dm_region_hash       G",
+"     enclosure            G",
+"     pata_acpi            G",
 NULL               
 };
 
diff --git a/kernel.c b/kernel.c
index 2dac4ed..eb5f2a5 100755
--- a/kernel.c
+++ b/kernel.c
@@ -22,6 +22,7 @@
 #include <ctype.h>
 
 static void do_module_cmd(ulong, char *, ulong, char *, char *);
+static void show_module_taint(int);
 static char *find_module_objfile(char *, char *, char *);
 static char *module_objfile_search(char *, char *, char *);
 static char *get_loadavg(char *);
@@ -3220,6 +3221,8 @@ irregularity:
 #define DELETE_ALL_MODULE_SYMBOLS     (5)
 #define REMOTE_MODULE_SAVE_MSG        (6)
 #define REINIT_MODULES                (7)
+#define LIST_ALL_MODULE_TAINT         (8)
+#define LIST_ALL_MODULE_TAINT_OLD     (9)
 
 void
 cmd_mod(void)
@@ -3294,7 +3297,7 @@ cmd_mod(void)
 	address = 0;
 	flag = LIST_MODULE_HDR;
 
-        while ((c = getopt(argcnt, args, "Rd:Ds:So")) != EOF) {
+        while ((c = getopt(argcnt, args, "Rd:Ds:SoTt")) != EOF) {
                 switch(c)
 		{
                 case 'R':
@@ -3365,6 +3368,20 @@ cmd_mod(void)
 				cmd_usage(pc->curcmd, SYNOPSIS);
 			break;
 
+		case 'T':
+                        if (flag)
+				cmd_usage(pc->curcmd, SYNOPSIS);
+			else
+				flag = LIST_ALL_MODULE_TAINT;
+			break;
+
+		case 't':
+                        if (flag)
+				cmd_usage(pc->curcmd, SYNOPSIS);
+			else
+				flag = LIST_ALL_MODULE_TAINT_OLD;
+			break;
+
 		default:
 			argerrs++;
 			break;
@@ -3485,6 +3502,163 @@ check_specified_module_tree(char *module, char *gdb_buffer)
 	return retval;
 }
 
+void
+show_module_taint(int flag)
+{
+	int i, j, bx = 0;
+	struct load_module *lm;
+	int maxnamelen = 0;
+	char buf[BUFSIZE];
+	char buf1[BUFSIZE];
+	int gpgsig_ok, license_gplok;
+	struct syment *sp = NULL;
+	uint *taintsp, taints, tnt_struct = 0;
+	uint8_t tnt_bit;
+	char tnt_true, tnt_false;
+	int found = FALSE;
+
+	if (flag != LIST_ALL_MODULE_TAINT_OLD &&
+		!kernel_symbol_exists("tnts") &&
+		!MEMBER_EXISTS("tnt", "bit") &&
+		!MEMBER_EXISTS("tnt", "true") &&
+		!MEMBER_EXISTS("tnt", "false"))
+			error(FATAL,
+				"tnts[] array does not exists in this kernel.\n");
+
+	if (!MEMBER_EXISTS("module", "taints") &&
+		!MEMBER_EXISTS("module", "license_gplok"))
+			error(FATAL,
+				"neither taints nor license_gplok exists.\n");
+
+	i = 0;
+	do {
+		lm = &st->load_modules[i];
+
+		if (MEMBER_EXISTS("module", "taints")) {
+			readmem(lm->module_struct + MEMBER_OFFSET("module", "taints"),
+				KVADDR, &taints, sizeof(uint), "module taints",
+				FAULT_ON_ERROR);
+
+			if (taints)
+				break;
+		} else {
+			readmem(lm->module_struct + MEMBER_OFFSET("module", "license_gplok"),
+				KVADDR, &license_gplok, sizeof(int), "module license_gplok",
+				FAULT_ON_ERROR);
+
+			if (license_gplok)
+				break;
+		}
+		i++;
+
+		if (i >= kt->mods_installed)
+			error(FATAL, "no tainted modules.\n");
+
+	} while (i < kt->mods_installed);
+
+	if (symbol_exists("tnts") &&
+		flag != LIST_ALL_MODULE_TAINT_OLD) {
+		sp = symbol_search("tnts");
+		tnt_struct = STRUCT_SIZE("struct tnt");
+	}
+
+	for (i = 0; i < kt->mods_installed; i++) {
+		lm = &st->load_modules[i];
+		maxnamelen = strlen(lm->mod_name) > maxnamelen ?
+			strlen(lm->mod_name) : maxnamelen;
+	}
+
+	fprintf(fp, "%s  TAINT\n",
+		mkstring(buf1, maxnamelen, LJUST, "NAME"));
+
+	for (i = 0; i < st->mods_installed; i++) {
+		lm = &st->load_modules[i];
+
+		if (flag != LIST_ALL_MODULE_TAINT) {
+
+			if (MEMBER_EXISTS("module", "license_gplok")) {
+				readmem(lm->module_struct + MEMBER_OFFSET("module", "license_gplok"),
+					KVADDR, &license_gplok, sizeof(int), "module license_gplok",
+					FAULT_ON_ERROR);
+
+				if (license_gplok)
+					found = TRUE;
+			} else {
+
+				readmem(lm->module_struct + MEMBER_OFFSET("module", "taints"),
+					KVADDR, &taints, sizeof(uint), "module taints",
+					FAULT_ON_ERROR);
+
+				if (taints)
+					found = TRUE;
+			}
+
+		} else {
+
+			readmem(lm->module_struct + MEMBER_OFFSET("module", "taints"),
+				KVADDR, &taints, sizeof(uint), "module taints",
+				FAULT_ON_ERROR);
+
+			taintsp = &taints;
+
+			if (taints) {
+				for (j = 0; j < (get_array_length("tnts", NULL, 0)*tnt_struct);
+					j += tnt_struct) {
+
+					readmem((sp->value + j) + MEMBER_OFFSET("tnt", "bit"),
+						KVADDR, &tnt_bit, sizeof(uint8_t), "tnt bit",
+						FAULT_ON_ERROR);
+
+					if (NUM_IN_BITMAP(taintsp, tnt_bit)) {
+						readmem((sp->value + j) + MEMBER_OFFSET("tnt", "true"),
+							KVADDR, &tnt_true, sizeof(char), "tnt true",
+							FAULT_ON_ERROR);
+
+						buf[bx++] = tnt_true;
+						found = TRUE;
+					} else {
+						readmem((sp->value + j) + MEMBER_OFFSET("tnt", "false"),
+							KVADDR, &tnt_false, sizeof(char), "tnt false",
+							FAULT_ON_ERROR);
+
+						if (tnt_false != ' ' && tnt_false != '-') {
+							buf[bx++] = tnt_false;
+							found = TRUE;
+						}
+					}
+
+				}
+			}
+
+			if (MEMBER_EXISTS("module", "gpgsig_ok")) {
+				readmem(lm->module_struct + MEMBER_OFFSET("module", "gpgsig_ok"),
+					KVADDR, &gpgsig_ok, sizeof(int), "module gpgsig_ok",
+					FAULT_ON_ERROR);
+
+				if (!gpgsig_ok) {
+					buf[bx++] = '(';
+					buf[bx++] = 'U';
+					buf[bx++] = ')';
+					found = TRUE;
+				}
+			}
+			buf[bx++] = '\0';
+			bx = 0;
+		}
+
+		if (found) {
+			if (flag != LIST_ALL_MODULE_TAINT_OLD)
+				fprintf(fp, "%s  %s\n", mkstring(buf1, maxnamelen,
+					LJUST, lm->mod_name), buf);
+			else
+				fprintf(fp, "%s  0x%x\n", mkstring(buf1, maxnamelen,
+					LJUST, lm->mod_name), (MEMBER_EXISTS("module", "taints"))
+						? taints : license_gplok);
+
+			found = FALSE;
+		}
+	}
+}
 
 /*
  *  Do the simple list work for cmd_mod().
@@ -3655,6 +3829,11 @@ do_module_cmd(ulong flag, char *modref, ulong address,
 		reinit_modules();
         	do_module_cmd(LIST_MODULE_HDR, NULL, 0, NULL, NULL);
 		break;
+
+	case LIST_ALL_MODULE_TAINT:
+	case LIST_ALL_MODULE_TAINT_OLD:
+		show_module_taint(flag);
+		break;
 	}
 }
 
