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
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility