--- crash-7.0.0/help.c.orig
+++ crash-7.0.0/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|-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,17 @@ 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  Display the contents of the module's \"taints\" bitmask",
+"                       if it is non-zero.  When possible, the \"taints\" bits",
+"                       are translated to symbolic letters of the taint type;",
+"                       otherwise the hexadecimal value is shown.  In older",
+"                       kernels, the contents of the \"license_gplok\" field is",
+"                       displayed in hexadecimal if it is non-zero; the field",
+"                       may be either a bitmask or a boolean, depending upon the",
+"                       kernel version.  The relevant kernel sources should be",
+"                       consulted for the meaning of the letter(s) or hexadecimal",
+"                       bit value(s).  For modules that have a \"gpgsig_ok\" field",
+"                       that is zero (unsigned), the notation \"(U)\" is shown.",
 "                   -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.",
@@ -4673,6 +4684,21 @@ char *help_mod[] = {
 "    c806e000  autofs       9316  (not loaded)",
 "    c8072000  nfsd       151896  (not loaded)",
 "    c80a1000  mdacon       3556  (not loaded)",
+" ",
+"  Display modules that are \"tainted\", where in this case",
+"  where they are proprietary and unsigned:",
+" ",
+"    %s> mod -t",
+"    NAME      TAINT",
+"    vxspec    P(U)",
+"    vxportal  P(U)",
+"    fdd       P(U)",
+"    vxfs      P(U)",
+"    vxdmp     P(U)",
+"    vxio      P(U)",
+"    vxglm     P(U)",
+"    vxgms     P(U)",
+"    vxodm     P(U)",
 NULL               
 };
 
--- crash-7.0.0/defs.h.orig
+++ crash-7.0.0/defs.h
@@ -1867,6 +1867,12 @@ struct offset_table {
 	long ktime_t_tv64;
 	long ktime_t_sec;
 	long ktime_t_nsec;
+	long module_taints;
+	long module_gpgsig_ok;
+	long module_license_gplok;
+	long tnt_bit;
+	long tnt_true;
+	long tnt_false;
 };
 
 struct size_table {         /* stash of commonly-used sizes */
@@ -2006,6 +2012,7 @@ struct size_table {         /* stash of
 	long vmap_area;
 	long hrtimer_clock_base;
 	long hrtimer_base;
+	long tnt;
 };
 
 struct array_table {
--- crash-7.0.0/kernel.c.orig
+++ crash-7.0.0/kernel.c
@@ -22,6 +22,7 @@
 #include <ctype.h>
 
 static void do_module_cmd(ulong, char *, ulong, char *, char *);
+static void show_module_taint(void);
 static char *find_module_objfile(char *, char *, char *);
 static char *module_objfile_search(char *, char *, char *);
 static char *get_loadavg(char *);
@@ -3221,6 +3222,7 @@ irregularity:
 #define DELETE_ALL_MODULE_SYMBOLS     (5)
 #define REMOTE_MODULE_SAVE_MSG        (6)
 #define REINIT_MODULES                (7)
+#define LIST_ALL_MODULE_TAINT         (8)
 
 void
 cmd_mod(void)
@@ -3295,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:Sot")) != EOF) {
                 switch(c)
 		{
                 case 'R':
@@ -3366,6 +3368,13 @@ 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;
+
 		default:
 			argerrs++;
 			break;
@@ -3486,6 +3495,146 @@ check_specified_module_tree(char *module
 	return retval;
 }
 
+static void
+show_module_taint(void)
+{
+	int i, j, bx;
+	struct load_module *lm;
+	int maxnamelen;
+	int found;
+	char buf1[BUFSIZE];
+	char buf2[BUFSIZE];
+	int gpgsig_ok, license_gplok;
+	struct syment *sp;
+	uint *taintsp, taints;
+	uint8_t tnt_bit;
+	char tnt_true, tnt_false;
+	int tnts_exists, tnts_len;
+	ulong tnts_addr;
+	char *modbuf;
+
+	if (INVALID_MEMBER(module_taints) &&
+	    INVALID_MEMBER(module_license_gplok)) {
+		MEMBER_OFFSET_INIT(module_taints, "module", "taints");
+		MEMBER_OFFSET_INIT(module_license_gplok, 
+			"module", "license_gplok");
+		MEMBER_OFFSET_INIT(module_gpgsig_ok, "module", "gpgsig_ok");
+		STRUCT_SIZE_INIT(tnt, "tnt");
+		MEMBER_OFFSET_INIT(tnt_bit, "tnt", "bit");
+		MEMBER_OFFSET_INIT(tnt_true, "tnt", "true");
+		MEMBER_OFFSET_INIT(tnt_false, "tnt", "false");
+	}
+
+	if (INVALID_MEMBER(module_taints) &&
+	    INVALID_MEMBER(module_license_gplok))
+		option_not_supported('t');
+
+	modbuf = GETBUF(SIZE(module));
+
+	for (i = found = maxnamelen = 0; i < kt->mods_installed; i++) {
+		lm = &st->load_modules[i];
+
+		readmem(lm->module_struct, KVADDR, modbuf, SIZE(module),
+			"module struct", FAULT_ON_ERROR);
+
+		taints = VALID_MEMBER(module_taints) ?
+			UINT(modbuf + OFFSET(module_taints)) : 0;
+		license_gplok = VALID_MEMBER(module_license_gplok) ? 
+			INT(modbuf + OFFSET(module_license_gplok)) : 0;
+		gpgsig_ok = VALID_MEMBER(module_gpgsig_ok) ?
+			INT(modbuf + OFFSET(module_gpgsig_ok)) : 1;
+
+		if (taints || license_gplok || !gpgsig_ok) {
+			found++;
+			maxnamelen = strlen(lm->mod_name) > maxnamelen ?
+				strlen(lm->mod_name) : maxnamelen;
+		}
+			
+	}
+
+	if (!found) {
+		fprintf(fp, "no tainted modules\n");
+		FREEBUF(modbuf);
+		return;
+	}
+
+	if (VALID_STRUCT(tnt) && (sp = symbol_search("tnts"))) {
+		tnts_exists = TRUE;
+		tnts_len = get_array_length("tnts", NULL, 0);
+		tnts_addr = sp->value;
+	} else {
+		tnts_exists = FALSE;
+		tnts_len = 0;
+		tnts_addr = 0;
+	}
+
+	fprintf(fp, "%s  %s\n",
+		mkstring(buf2, maxnamelen, LJUST, "NAME"),
+		VALID_MEMBER(module_taints) ? "TAINTS" : "LICENSE_GPLOK");
+
+	for (i = 0; i < st->mods_installed; i++) {
+
+		lm = &st->load_modules[i];
+		bx = 0;
+		buf1[0] = '\0';
+
+		readmem(lm->module_struct, KVADDR, modbuf, SIZE(module),
+			"module struct", FAULT_ON_ERROR);
+
+		taints = VALID_MEMBER(module_taints) ?
+			UINT(modbuf + OFFSET(module_taints)) : 0;
+		license_gplok = VALID_MEMBER(module_license_gplok) ? 
+			INT(modbuf + OFFSET(module_license_gplok)) : 0;
+		gpgsig_ok = VALID_MEMBER(module_gpgsig_ok) ?
+			INT(modbuf + OFFSET(module_gpgsig_ok)) : 1;
+
+		if (!taints && !license_gplok && gpgsig_ok)
+			continue;
+
+		if (tnts_exists && taints) {
+			taintsp = &taints;
+			for (j = 0; j < (tnts_len * SIZE(tnt)); j += SIZE(tnt)) {
+				readmem((tnts_addr + j) + OFFSET(tnt_bit),
+					KVADDR, &tnt_bit, sizeof(uint8_t), 
+					"tnt bit", FAULT_ON_ERROR);
+
+				if (NUM_IN_BITMAP(taintsp, tnt_bit)) {
+					readmem((tnts_addr + j) + OFFSET(tnt_true),
+						KVADDR, &tnt_true, sizeof(char), 
+						"tnt true", FAULT_ON_ERROR);
+					buf1[bx++] = tnt_true;
+				} else {
+					readmem((tnts_addr + j) + OFFSET(tnt_false),
+						KVADDR, &tnt_false, sizeof(char), 
+						"tnt false", FAULT_ON_ERROR);
+					if (tnt_false != ' ' && tnt_false != '-' &&
+					    tnt_false != 'G')
+						buf1[bx++] = tnt_false;
+				}
+
+			}
+		}
+
+		if (VALID_MEMBER(module_gpgsig_ok) && !gpgsig_ok) {
+			buf1[bx++] = '(';
+			buf1[bx++] = 'U';
+			buf1[bx++] = ')';
+		}
+
+		buf1[bx++] = '\0';
+
+		if (tnts_exists)
+			fprintf(fp, "%s  %s\n", mkstring(buf2, maxnamelen,
+				LJUST, lm->mod_name), buf1);
+		else
+			fprintf(fp, "%s  %x%s\n", mkstring(buf2, maxnamelen,
+				LJUST, lm->mod_name), 
+				VALID_MEMBER(module_taints) ? 
+				taints : license_gplok, buf1);
+	}
+
+	FREEBUF(modbuf);
+}
 
 /*
  *  Do the simple list work for cmd_mod().
@@ -3656,6 +3805,10 @@ do_module_cmd(ulong flag, char *modref,
 		reinit_modules();
         	do_module_cmd(LIST_MODULE_HDR, NULL, 0, NULL, NULL);
 		break;
+
+	case LIST_ALL_MODULE_TAINT:
+		show_module_taint();
+		break;
 	}
 }
 
--- crash-7.0.0/symbols.c.orig
+++ crash-7.0.0/symbols.c
@@ -7839,6 +7839,16 @@ dump_offset_table(char *spec, ulong make
         fprintf(fp, "     kallsyms_section_name_off: %ld\n",
         	OFFSET(kallsyms_section_name_off));
 
+	fprintf(fp, "                 module_taints: %ld\n",
+		OFFSET(module_taints));
+	fprintf(fp, "          module_license_gplok: %ld\n",
+		OFFSET(module_license_gplok));
+	fprintf(fp, "              module_gpgsig_ok: %ld\n",
+		OFFSET(module_gpgsig_ok));
+	fprintf(fp, "                       tnt_bit: %ld\n", OFFSET(tnt_bit));
+	fprintf(fp, "                      tnt_true: %ld\n", OFFSET(tnt_true));
+	fprintf(fp, "                     tnt_false: %ld\n", OFFSET(tnt_false));
+
 	fprintf(fp, "                     page_next: %ld\n", OFFSET(page_next));
 	fprintf(fp, "                     page_prev: %ld\n", OFFSET(page_prev));
 	fprintf(fp, "                page_next_hash: %ld\n", 
@@ -9226,6 +9236,8 @@ dump_offset_table(char *spec, ulong make
 		SIZE(hrtimer_clock_base));
 	fprintf(fp, "                  hrtimer_base: %ld\n",
 		SIZE(hrtimer_base));
+	fprintf(fp, "                           tnt: %ld\n",
+		SIZE(tnt));
 
         fprintf(fp, "\n                   array_table:\n");
 	/*
