diff options
author | Florin Malita <fmalita@gmail.com> | 2006-10-11 04:21:48 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-11 14:14:21 -0400 |
commit | fa3ba2e81ea23416272a22009bba95954c81969c (patch) | |
tree | cd1ab15dcf1130a4920ca9396cb91aaff4b0dcf6 /kernel/module.c | |
parent | 3719bc5c22c9025bf1c909fe8b527ebf1de9a153 (diff) |
[PATCH] fix Module taint flags listing in Oops/panic
Module taint flags listing in Oops/panic has a couple of issues:
* taint_flags() doesn't null-terminate the buffer after printing the flags
* per-module taints are only set if the kernel is not already tainted
(with that particular flag) => only the first offending module gets its
taint info correctly updated
Some additional changes:
* 'license_gplok' is no longer needed - equivalent to !(taints &
TAINT_PROPRIETARY_MODULE) - so we can drop it from struct module *
exporting module taint info via /proc/module:
pwc 88576 0 - Live 0xf8c32000
evilmod 6784 1 pwc, Live 0xf8bbf000 (PF)
Signed-off-by: Florin Malita <fmalita@gmail.com>
Cc: "Randy.Dunlap" <rdunlap@xenotime.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 94 |
1 files changed, 49 insertions, 45 deletions
diff --git a/kernel/module.c b/kernel/module.c index 7f60e782de1e..67009bd56c52 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -87,6 +87,12 @@ static inline int strong_try_module_get(struct module *mod) | |||
87 | return try_module_get(mod); | 87 | return try_module_get(mod); |
88 | } | 88 | } |
89 | 89 | ||
90 | static inline void add_taint_module(struct module *mod, unsigned flag) | ||
91 | { | ||
92 | add_taint(flag); | ||
93 | mod->taints |= flag; | ||
94 | } | ||
95 | |||
90 | /* A thread that wants to hold a reference to a module only while it | 96 | /* A thread that wants to hold a reference to a module only while it |
91 | * is running can call ths to safely exit. | 97 | * is running can call ths to safely exit. |
92 | * nfsd and lockd use this. | 98 | * nfsd and lockd use this. |
@@ -847,12 +853,10 @@ static int check_version(Elf_Shdr *sechdrs, | |||
847 | return 0; | 853 | return 0; |
848 | } | 854 | } |
849 | /* Not in module's version table. OK, but that taints the kernel. */ | 855 | /* Not in module's version table. OK, but that taints the kernel. */ |
850 | if (!(tainted & TAINT_FORCED_MODULE)) { | 856 | if (!(tainted & TAINT_FORCED_MODULE)) |
851 | printk("%s: no version for \"%s\" found: kernel tainted.\n", | 857 | printk("%s: no version for \"%s\" found: kernel tainted.\n", |
852 | mod->name, symname); | 858 | mod->name, symname); |
853 | add_taint(TAINT_FORCED_MODULE); | 859 | add_taint_module(mod, TAINT_FORCED_MODULE); |
854 | mod->taints |= TAINT_FORCED_MODULE; | ||
855 | } | ||
856 | return 1; | 860 | return 1; |
857 | } | 861 | } |
858 | 862 | ||
@@ -910,7 +914,8 @@ static unsigned long resolve_symbol(Elf_Shdr *sechdrs, | |||
910 | unsigned long ret; | 914 | unsigned long ret; |
911 | const unsigned long *crc; | 915 | const unsigned long *crc; |
912 | 916 | ||
913 | ret = __find_symbol(name, &owner, &crc, mod->license_gplok); | 917 | ret = __find_symbol(name, &owner, &crc, |
918 | !(mod->taints & TAINT_PROPRIETARY_MODULE)); | ||
914 | if (ret) { | 919 | if (ret) { |
915 | /* use_module can fail due to OOM, or module unloading */ | 920 | /* use_module can fail due to OOM, or module unloading */ |
916 | if (!check_version(sechdrs, versindex, name, mod, crc) || | 921 | if (!check_version(sechdrs, versindex, name, mod, crc) || |
@@ -1335,12 +1340,11 @@ static void set_license(struct module *mod, const char *license) | |||
1335 | if (!license) | 1340 | if (!license) |
1336 | license = "unspecified"; | 1341 | license = "unspecified"; |
1337 | 1342 | ||
1338 | mod->license_gplok = license_is_gpl_compatible(license); | 1343 | if (!license_is_gpl_compatible(license)) { |
1339 | if (!mod->license_gplok && !(tainted & TAINT_PROPRIETARY_MODULE)) { | 1344 | if (!(tainted & TAINT_PROPRIETARY_MODULE)) |
1340 | printk(KERN_WARNING "%s: module license '%s' taints kernel.\n", | 1345 | printk(KERN_WARNING "%s: module license '%s' taints" |
1341 | mod->name, license); | 1346 | "kernel.\n", mod->name, license); |
1342 | add_taint(TAINT_PROPRIETARY_MODULE); | 1347 | add_taint_module(mod, TAINT_PROPRIETARY_MODULE); |
1343 | mod->taints |= TAINT_PROPRIETARY_MODULE; | ||
1344 | } | 1348 | } |
1345 | } | 1349 | } |
1346 | 1350 | ||
@@ -1619,8 +1623,7 @@ static struct module *load_module(void __user *umod, | |||
1619 | modmagic = get_modinfo(sechdrs, infoindex, "vermagic"); | 1623 | modmagic = get_modinfo(sechdrs, infoindex, "vermagic"); |
1620 | /* This is allowed: modprobe --force will invalidate it. */ | 1624 | /* This is allowed: modprobe --force will invalidate it. */ |
1621 | if (!modmagic) { | 1625 | if (!modmagic) { |
1622 | add_taint(TAINT_FORCED_MODULE); | 1626 | add_taint_module(mod, TAINT_FORCED_MODULE); |
1623 | mod->taints |= TAINT_FORCED_MODULE; | ||
1624 | printk(KERN_WARNING "%s: no version magic, tainting kernel.\n", | 1627 | printk(KERN_WARNING "%s: no version magic, tainting kernel.\n", |
1625 | mod->name); | 1628 | mod->name); |
1626 | } else if (!same_magic(modmagic, vermagic)) { | 1629 | } else if (!same_magic(modmagic, vermagic)) { |
@@ -1714,14 +1717,10 @@ static struct module *load_module(void __user *umod, | |||
1714 | /* Set up license info based on the info section */ | 1717 | /* Set up license info based on the info section */ |
1715 | set_license(mod, get_modinfo(sechdrs, infoindex, "license")); | 1718 | set_license(mod, get_modinfo(sechdrs, infoindex, "license")); |
1716 | 1719 | ||
1717 | if (strcmp(mod->name, "ndiswrapper") == 0) { | 1720 | if (strcmp(mod->name, "ndiswrapper") == 0) |
1718 | add_taint(TAINT_PROPRIETARY_MODULE); | 1721 | add_taint_module(mod, TAINT_PROPRIETARY_MODULE); |
1719 | mod->taints |= TAINT_PROPRIETARY_MODULE; | 1722 | if (strcmp(mod->name, "driverloader") == 0) |
1720 | } | 1723 | add_taint_module(mod, TAINT_PROPRIETARY_MODULE); |
1721 | if (strcmp(mod->name, "driverloader") == 0) { | ||
1722 | add_taint(TAINT_PROPRIETARY_MODULE); | ||
1723 | mod->taints |= TAINT_PROPRIETARY_MODULE; | ||
1724 | } | ||
1725 | 1724 | ||
1726 | /* Set up MODINFO_ATTR fields */ | 1725 | /* Set up MODINFO_ATTR fields */ |
1727 | setup_modinfo(mod, sechdrs, infoindex); | 1726 | setup_modinfo(mod, sechdrs, infoindex); |
@@ -1766,8 +1765,7 @@ static struct module *load_module(void __user *umod, | |||
1766 | (mod->num_unused_gpl_syms && !unusedgplcrcindex)) { | 1765 | (mod->num_unused_gpl_syms && !unusedgplcrcindex)) { |
1767 | printk(KERN_WARNING "%s: No versions for exported symbols." | 1766 | printk(KERN_WARNING "%s: No versions for exported symbols." |
1768 | " Tainting kernel.\n", mod->name); | 1767 | " Tainting kernel.\n", mod->name); |
1769 | add_taint(TAINT_FORCED_MODULE); | 1768 | add_taint_module(mod, TAINT_FORCED_MODULE); |
1770 | mod->taints |= TAINT_FORCED_MODULE; | ||
1771 | } | 1769 | } |
1772 | #endif | 1770 | #endif |
1773 | 1771 | ||
@@ -2132,9 +2130,33 @@ static void m_stop(struct seq_file *m, void *p) | |||
2132 | mutex_unlock(&module_mutex); | 2130 | mutex_unlock(&module_mutex); |
2133 | } | 2131 | } |
2134 | 2132 | ||
2133 | static char *taint_flags(unsigned int taints, char *buf) | ||
2134 | { | ||
2135 | int bx = 0; | ||
2136 | |||
2137 | if (taints) { | ||
2138 | buf[bx++] = '('; | ||
2139 | if (taints & TAINT_PROPRIETARY_MODULE) | ||
2140 | buf[bx++] = 'P'; | ||
2141 | if (taints & TAINT_FORCED_MODULE) | ||
2142 | buf[bx++] = 'F'; | ||
2143 | /* | ||
2144 | * TAINT_FORCED_RMMOD: could be added. | ||
2145 | * TAINT_UNSAFE_SMP, TAINT_MACHINE_CHECK, TAINT_BAD_PAGE don't | ||
2146 | * apply to modules. | ||
2147 | */ | ||
2148 | buf[bx++] = ')'; | ||
2149 | } | ||
2150 | buf[bx] = '\0'; | ||
2151 | |||
2152 | return buf; | ||
2153 | } | ||
2154 | |||
2135 | static int m_show(struct seq_file *m, void *p) | 2155 | static int m_show(struct seq_file *m, void *p) |
2136 | { | 2156 | { |
2137 | struct module *mod = list_entry(p, struct module, list); | 2157 | struct module *mod = list_entry(p, struct module, list); |
2158 | char buf[8]; | ||
2159 | |||
2138 | seq_printf(m, "%s %lu", | 2160 | seq_printf(m, "%s %lu", |
2139 | mod->name, mod->init_size + mod->core_size); | 2161 | mod->name, mod->init_size + mod->core_size); |
2140 | print_unload_info(m, mod); | 2162 | print_unload_info(m, mod); |
@@ -2147,6 +2169,10 @@ static int m_show(struct seq_file *m, void *p) | |||
2147 | /* Used by oprofile and other similar tools. */ | 2169 | /* Used by oprofile and other similar tools. */ |
2148 | seq_printf(m, " 0x%p", mod->module_core); | 2170 | seq_printf(m, " 0x%p", mod->module_core); |
2149 | 2171 | ||
2172 | /* Taints info */ | ||
2173 | if (mod->taints) | ||
2174 | seq_printf(m, " %s", taint_flags(mod->taints, buf)); | ||
2175 | |||
2150 | seq_printf(m, "\n"); | 2176 | seq_printf(m, "\n"); |
2151 | return 0; | 2177 | return 0; |
2152 | } | 2178 | } |
@@ -2235,28 +2261,6 @@ struct module *module_text_address(unsigned long addr) | |||
2235 | return mod; | 2261 | return mod; |
2236 | } | 2262 | } |
2237 | 2263 | ||
2238 | static char *taint_flags(unsigned int taints, char *buf) | ||
2239 | { | ||
2240 | *buf = '\0'; | ||
2241 | if (taints) { | ||
2242 | int bx; | ||
2243 | |||
2244 | buf[0] = '('; | ||
2245 | bx = 1; | ||
2246 | if (taints & TAINT_PROPRIETARY_MODULE) | ||
2247 | buf[bx++] = 'P'; | ||
2248 | if (taints & TAINT_FORCED_MODULE) | ||
2249 | buf[bx++] = 'F'; | ||
2250 | /* | ||
2251 | * TAINT_FORCED_RMMOD: could be added. | ||
2252 | * TAINT_UNSAFE_SMP, TAINT_MACHINE_CHECK, TAINT_BAD_PAGE don't | ||
2253 | * apply to modules. | ||
2254 | */ | ||
2255 | buf[bx] = ')'; | ||
2256 | } | ||
2257 | return buf; | ||
2258 | } | ||
2259 | |||
2260 | /* Don't grab lock, we're oopsing. */ | 2264 | /* Don't grab lock, we're oopsing. */ |
2261 | void print_modules(void) | 2265 | void print_modules(void) |
2262 | { | 2266 | { |