Hi Dave, Sorry about the delay. I've finally found the time to attempt another version. As per your request, I've updated *help_mod[] to document the -T option. Also in this particular version, I omit ' ' and '-', when false, as I'm under the impression that we're only interested in true values as per module_flags() (since 2.6.25). I suspect that there shouldn't be a situation where a module isn't tainted since every module is either proprietary license or GPL. However, if this is not acceptable I can change this behaviour. For module.gpgsig_ok case (as seen in kernel-2.6.32-1.el6), I've decided to follow the same logic to highlight "(U)" to the user, as per print_modules(). With regards to module.sig_ok, this is handled, as seen under 3.8.9-200.fc18: nf_nat G bnx2i G ip6t_REJECT G nf_defrag_ipv6 G be2iscsi G tun G test GFO For pre 2.6.28 kernels, I'll work on a solution that simply displays the bit number to then refer the user to the relevant kernel source for details on what the bit number means, as per your suggestion. I just wanted to get this version out to the mailing list for review. Cheers, Aaron --8<-- help.c | 18 ++++++++- kernel.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 140 insertions(+), 2 deletion
diff --git a/help.c b/help.c index c9ae57e..c5eba7e 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 | -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,7 @@ 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 Shows each module's taints flags (if supported).", " -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 +4674,21 @@ char *help_mod[] = { " c806e000 autofs 9316 (not loaded)", " c8072000 nfsd 151896 (not loaded)", " c80a1000 mdacon 3556 (not loaded)", +" ", +" Display the taints flags for each module on kernels which support the", +" tnts[] array:", +" ", +" %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..7b20247 100755 --- a/kernel.c +++ b/kernel.c @@ -22,6 +22,8 @@ #include <ctype.h> static void do_module_cmd(ulong, char *, ulong, char *, char *); +static void show_module_taint(void); +static int is_module_taint(struct load_module *, char *, int *); static char *find_module_objfile(char *, char *, char *); static char *module_objfile_search(char *, char *, char *); static char *get_loadavg(char *); @@ -3220,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) @@ -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,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; @@ -3485,6 +3495,114 @@ check_specified_module_tree(char *module, char *gdb_buffer) return retval; } +int +is_module_taint(struct load_module *lm, char *buf, int *maxtnts_len) +{ + int gpgsig_ok; + struct syment *sp = NULL; + ulong taints, tnts; + uint tnt_size; + ulong *taintsp; + uint8_t tnt_bit; + char tnt_true, tnt_false; + uint i, bx = 0; + int found = FALSE; + + tnt_size = STRUCT_SIZE("struct tnt"); + sp = symbol_search("tnts"); + + tnts = sp->value; + + if (MEMBER_EXISTS("module", "taints")) { + readmem(lm->module_struct + MEMBER_OFFSET("module", "taints"), + KVADDR, &taints, sizeof(ulong), "module taints", + FAULT_ON_ERROR); + + taintsp = &taints; + + if (taints) { + for (i = 0; i < (get_array_length("tnts", NULL, 0)*tnt_size); i += tnt_size) { + readmem((tnts + i) + MEMBER_OFFSET("tnt", "bit"), + KVADDR, &tnt_bit, sizeof(uint8_t), "tnt bit", + FAULT_ON_ERROR); + + if (NUM_IN_BITMAP(taintsp, tnt_bit)) { + readmem((tnts + i) + MEMBER_OFFSET("tnt", "true"), + KVADDR, &tnt_true, sizeof(char), "tnt true", + FAULT_ON_ERROR); + buf[bx++] = tnt_true; + found = TRUE; + } else { + readmem((tnts + i) + 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'; + *maxtnts_len = bx; + return found; +} + +void +show_module_taint() +{ + int i; + struct load_module *lm; + int maxnamelen = 0; + int maxtnts_len = 0; + char buf1[BUFSIZE]; + char buf2[BUFSIZE]; + + if (!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"); + } + + 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 %s\n", + mkstring(buf1, maxnamelen, LJUST, "NAME"), + mkstring(buf2, 5, LJUST, "TAINT")); + + for (i = 0; i < st->mods_installed; i++) { + lm = &st->load_modules[i]; + + if (is_module_taint(lm, buf2, &maxtnts_len)) { + fprintf(fp, "%s ", mkstring(buf1, maxnamelen, + LJUST, lm->mod_name)); + fprintf(fp, "%s\n", mkstring(buf2, maxtnts_len, + LJUST, buf2)); + } + } +} /* * Do the simple list work for cmd_mod(). @@ -3655,6 +3773,10 @@ 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: + show_module_taint(); + break; } }
-- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility