[Crash-utility] Re: [PATCH] symbols: handle module symbols outside strbuf

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



HAGIO KAZUHITO(萩尾 一仁)	<k-hagio-ab@xxxxxxx> writes:

> On 2023/11/28 23:57, Stephen Brennan wrote:
>> Module symbol names can get overwritten by live patches or ksplice in
>> odd corner cases, so that the pointer no longer points within the string
>> buffer. Gracefully fallback to reading the string directly from the
>> kernel image in these cases, to avoid possible segmentation faults
>> reading outside the bounds of strbuf.
>>
>> Signed-off-by: Stephen Brennan <stephen.s.brennan@xxxxxxxxxx>
>> ---
>>
>> Hi folks - I encountered a segfault on a vmcore which had a module
>> symbol that had gotten its name overwritten by a ksplice (live patch).
>> It seems like there's not a guarantee that module symbol names _must_
>> live within the same symbol buffer, and there is even logic to prevent
>> reading too much data into strbuf in those cases.
>
> Thank you for the report and patch.
>
> To me, it seems like the logic is just to cap the buffer size because of
> adding BUFSIZE.
>
> If "last" is outside of a module range, your patch can fix it.  But if
> "first" is far outside (lower) of the module range, strbuflen becomes
> huge and crash tries to allocate a huge memory?  Is it possible by ksplice?

Hi Kazu, thanks for taking a look.

You're right, if first is far below the module range, then there would
be a separate bug, and my patch won't address it. I haven't seen a case
where the symbol name points below the module address range, but I
believe it's possible.

The replacement string comes from the ksplice module. So if the ksplice
module gets allocated to an address below the current module
(lm->mod_base), the case would happen.

A simple way to address this would be to abort the loop which calculates
first/last, if we encounter a string which is outside the module address
range. Something like this:

 for (i = first = last = 0; i < ngplsyms; i++) {
 	modsym = (union kernel_symbol *)
 	    (modsymbuf + (i * kernel_symbol_size));
+	if (modsym_name(gpl_syms, modsym, i) < lm->mod_base ||
+            modsym_name(gpl_syms, modsym, i) >= lm->mod_base + lm->mod_size) {
+		first = last = 0;
+		break;
+	}
 	if (!first
 	    || first > modsym_name(gpl_syms, modsym, i))
 		first = modsym_name(gpl_syms, modsym, i);
 	if (modsym_name(gpl_syms, modsym, i) > last)
 		last = modsym_name(gpl_syms, modsym, i);
 }

With this check, the buffer won't be created unless all the symbols are
in the contiguous region, so we don't need my added check from this
patche.

I will send an updated patch if you like this approach.

Thanks again,
Stephen

> Thanks,
> Kazu
>
>
>>
>> This patch simply ensures that symbol names which start outside of the
>> strbuf which we copied, are read directly from the kernel image, rather
>> than indexing past the bounds of strbuf. I encountered this in
>> store_module_symbols_v2() and have tested it there, but I replicated the
>> code to the other versions. I will try to test it out on the other
>> variants as well, but I thought I'd share the patch now.
>>
>>   symbols.c | 10 +++++-----
>>   1 file changed, 5 insertions(+), 5 deletions(-)
>>
>> diff --git a/symbols.c b/symbols.c
>> index 176c950..e70dd69 100644
>> --- a/symbols.c
>> +++ b/symbols.c
>> @@ -1704,7 +1704,7 @@ store_module_symbols_v1(ulong total, int mods_installed)
>>
>>   			BZERO(buf1, BUFSIZE);
>>
>> -			if (strbuf)
>> +			if (strbuf && (unsigned long)modsym->name - first < strbuflen)
>>   				strcpy(buf1,
>>   					&strbuf[(ulong)modsym->name - first]);
>>   			else
>> @@ -2080,7 +2080,7 @@ store_module_symbols_6_4(ulong total, int mods_installed)
>>
>>   			BZERO(buf1, BUFSIZE);
>>
>> -			if (strbuf)
>> +			if (strbuf && modsym_name(syms, modsym, i) - first < strbuflen)
>>   				strcpy(buf1, &strbuf[modsym_name(syms, modsym, i) - first]);
>>   			else
>>   				read_string(modsym_name(syms, modsym, i), buf1, BUFSIZE-1);
>> @@ -2148,7 +2148,7 @@ store_module_symbols_6_4(ulong total, int mods_installed)
>>
>>   			BZERO(buf1, BUFSIZE);
>>
>> -			if (strbuf)
>> +			if (strbuf && modsym_name(gpl_syms, modsym, i) - first < strbuflen)
>>   				strcpy(buf1, &strbuf[modsym_name(gpl_syms, modsym, i) - first]);
>>   			else
>>   				read_string(modsym_name(gpl_syms, modsym, i), buf1, BUFSIZE-1);
>> @@ -2456,7 +2456,7 @@ store_module_symbols_v2(ulong total, int mods_installed)
>>
>>   			BZERO(buf1, BUFSIZE);
>>
>> -			if (strbuf)
>> +			if (strbuf && modsym_name(syms, modsym, i) - first < strbuflen)
>>   				strcpy(buf1,
>>   					&strbuf[modsym_name(syms, modsym, i) - first]);
>>   			else
>> @@ -2529,7 +2529,7 @@ store_module_symbols_v2(ulong total, int mods_installed)
>>
>>   			BZERO(buf1, BUFSIZE);
>>
>> -			if (strbuf)
>> +			if (strbuf && modsym_name(gpl_syms, modsym, i) - first < strbuflen)
>>   				strcpy(buf1,
>>   					&strbuf[modsym_name(gpl_syms, modsym, i) - first]);
>>   			else
--
Crash-utility mailing list -- devel@xxxxxxxxxxxxxxxxxxxxxxxxxxx
To unsubscribe send an email to devel-leave@xxxxxxxxxxxxxxxxxxxxxxxxxxx
https://${domain_name}/admin/lists/devel.lists.crash-utility.osci.io/
Contribution Guidelines: https://github.com/crash-utility/crash/wiki




[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux