Subject: Fix segmentation violation in symbol_search
Fix a possible segmentation violation in crash if a module name
is not NUL-terminated. Although store_module_symbols_v2 complains
about an overly long module name, there are several problems
with the current approach:
1. The maximum size is hard-wired in defs.h and the current
constant doesn't even match struct module's name field size
on any architecture.
2. If the string is too long, it is probably not NUL-terminated,
so we can't use strlen() on it.
3. Even though only the first MAX_MOD_NAME-1 bytes are copied
to struct load_module, the _MODULE_* pseudo-symbol names are
generated from the unabridged module name. As a consequence,
they are not found further on in the loop at the end of
store_module_symbols_v2, so lm->mod_symtable remains NULL
for that module. The symbol_search() function is not
prepared for that situation and tries to dereference that
NULL pointer here:
sp = lm->mod_symtable;
sp_end = lm->mod_symend;
for ( ; sp <= sp_end; sp++) {
if (!pseudos && MODULE_PSEUDO_SYMBOL(sp))
^^^^
Regards,
Petr Tesarik
Subject: Fix segmentation violation in symbol_search
Fix a possible segmentation violation in crash if a module name
is not NUL-terminated. Although store_module_symbols_v2 complains
about an overly long module name, there are several problems
with the current approach:
1. The maximum size is hard-wired in defs.h and the current
constant doesn't even match struct module's name field size
on any architecture.
2. If the string is too long, it is probably not NUL-terminated,
so we can't use strlen() on it.
3. Even though only the first MAX_MOD_NAME-1 bytes are copied
to struct load_module, the _MODULE_* pseudo-symbol names are
generated from the unabridged module name. As a consequence,
they are not found further on in the loop at the end of
store_module_symbols_v2, so lm->mod_symtable remains NULL
for that module. The symbol_search() function is not
prepared for that situation and tries to dereference that
NULL pointer here:
sp = lm->mod_symtable;
sp_end = lm->mod_symend;
for ( ; sp <= sp_end; sp++) {
if (!pseudos && MODULE_PSEUDO_SYMBOL(sp))
^^^^
Signed-off-by: Petr Tesarik <[email protected]>
---
symbols.c | 30 +++++++++++++++++++++---------
1 file changed, 21 insertions(+), 9 deletions(-)
--- a/symbols.c
+++ b/symbols.c
@@ -1337,6 +1337,7 @@ store_module_symbols_v2(ulong total, int
char *strbuf, *modbuf, *modsymbuf;
struct syment *sp;
ulong first, last;
+ size_t max_mod_name;
st->mods_installed = mods_installed;
@@ -1367,6 +1368,16 @@ store_module_symbols_v2(ulong total, int
(st->mods_installed, sizeof(struct load_module))) == NULL)
error(FATAL, "load_module array malloc: %s\n", strerror(errno));
+ max_mod_name = MEMBER_SIZE("module", "name");
+ if (max_mod_name > MAX_MOD_NAME) {
+ error(INFO, "size of module.name is larger than MAX_MOD_NAME"
+ " (%d > %d)", max_mod_name, MAX_MOD_NAME);
+ max_mod_name = MAX_MOD_NAME;
+ } else if (max_mod_name <= 0) {
+ error(INFO, "cannot determine max module name length");
+ max_mod_name = MAX_MOD_NAME;
+ }
+
modbuf = GETBUF(SIZE(module));
modsymbuf = NULL;
m = mcnt = mod_next = 0;
@@ -1396,13 +1407,14 @@ store_module_symbols_v2(ulong total, int
lm->mod_base = ULONG(modbuf + OFFSET(module_module_core));
lm->module_struct = mod;
lm->mod_size = size;
- if (strlen(mod_name) < MAX_MOD_NAME)
+ if (memchr(mod_name, 0, max_mod_name))
strcpy(lm->mod_name, mod_name);
else {
- error(INFO,
- "module name greater than MAX_MOD_NAME: %s\n",
- mod_name);
- strncpy(lm->mod_name, mod_name, MAX_MOD_NAME-1);
+ memcpy(lm->mod_name, mod_name, max_mod_name-1);
+ lm->mod_name[max_mod_name-1] = '\0';
+ error(INFO,
+ "module name too long: %s (truncated)\n",
+ lm->mod_name);
}
if (CRASHDEBUG(3))
fprintf(fp,
@@ -1434,7 +1446,7 @@ store_module_symbols_v2(ulong total, int
st->ext_module_symtable[mcnt].value = lm->mod_base;
st->ext_module_symtable[mcnt].type = 'm';
st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL;
- sprintf(buf2, "%s%s", "_MODULE_START_", mod_name);
+ sprintf(buf2, "%s%s", "_MODULE_START_", lm->mod_name);
namespace_ctl(NAMESPACE_INSTALL, &st->ext_module_namespace,
&st->ext_module_symtable[mcnt], buf2);
lm_mcnt = mcnt;
@@ -1444,7 +1456,7 @@ store_module_symbols_v2(ulong total, int
st->ext_module_symtable[mcnt].value = lm->mod_init_module_ptr;
st->ext_module_symtable[mcnt].type = 'm';
st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL;
- sprintf(buf3, "%s%s", "_MODULE_INIT_START_", mod_name);
+ sprintf(buf3, "%s%s", "_MODULE_INIT_START_", lm->mod_name);
namespace_ctl(NAMESPACE_INSTALL,
&st->ext_module_namespace,
&st->ext_module_symtable[mcnt], buf3);
@@ -1627,7 +1639,7 @@ store_module_symbols_v2(ulong total, int
st->ext_module_symtable[mcnt].value = lm->mod_base + size;
st->ext_module_symtable[mcnt].type = 'm';
st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL;
- sprintf(buf2, "%s%s", "_MODULE_END_", mod_name);
+ sprintf(buf2, "%s%s", "_MODULE_END_", lm->mod_name);
namespace_ctl(NAMESPACE_INSTALL,
&st->ext_module_namespace,
&st->ext_module_symtable[mcnt], buf2);
@@ -1637,7 +1649,7 @@ store_module_symbols_v2(ulong total, int
st->ext_module_symtable[mcnt].value = lm->mod_init_module_ptr + lm->mod_init_size;
st->ext_module_symtable[mcnt].type = 'm';
st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL;
- sprintf(buf4, "%s%s", "_MODULE_INIT_END_", mod_name);
+ sprintf(buf4, "%s%s", "_MODULE_INIT_END_", lm->mod_name);
namespace_ctl(NAMESPACE_INSTALL,
&st->ext_module_namespace,
&st->ext_module_symtable[mcnt], buf4);
--
Crash-utility mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility