[libcamera-devel] [PATCH] libcamera: ipa_module: Fix implicit sign-extension in eflLoadSymbol

Umang Jain email at uajain.com
Fri Jun 5 11:04:25 CEST 2020


Hi Kieran,

On 6/5/20 1:31 PM, Kieran Bingham wrote:
> Hi Umang,
>
> On 05/06/2020 08:49, Umang Jain wrote:
>> This sub-expression of two (16 bits, unsigned) operands
>> 	(targetSymbol->st_shndx * eHdr->e_shentsize)
>> is promoted to type int (32 bits, signed) for multiplication and then
>> added to eHdr->e_shoff, which is of the type long (64 bits, unsigned).
>> Since eHdr->e_shoff is unsigned, the integer conversion rules dictates
>> that the other signed operand(i.e. the resultant of aforementioned
>> sub-expression) will be converted to unsigned type too. This causes
>> sign-extension for both of the above operands to match eHdr->e_shoff's
>> type and should be avoided.
>>
>> The solution is to explicitly cast one of the operands of the
>> sub-expression with unsigned int type. Hence, the other operand will be
>> integer promoted and the resultant will also be of unsigned int type,
>> not requiring to bother about a sign-extension.
>>
>> Reported-by: Coverity CID=280008
>> Reported-by: Coverity CID=280009
>> Reported-by: Coverity CID=280010
> Ohhh triple-whammy! :-D
>
>
>> Signed-off-by: Umang Jain <email at uajain.com>
>> ---
>>   src/libcamera/ipa_module.cpp | 6 ++++--
>>   1 file changed, 4 insertions(+), 2 deletions(-)
>>
>> diff --git a/src/libcamera/ipa_module.cpp b/src/libcamera/ipa_module.cpp
>> index 91534b6..dd7538b 100644
>> --- a/src/libcamera/ipa_module.cpp
>> +++ b/src/libcamera/ipa_module.cpp
>> @@ -102,7 +102,8 @@ Span<uint8_t> elfLoadSymbol(Span<uint8_t> elf, const char *symbol)
>>   	if (!eHdr)
>>   		return {};
>>   
>> -	off_t offset = eHdr->e_shoff + eHdr->e_shentsize * eHdr->e_shstrndx;
>> +	off_t offset = eHdr->e_shoff + ((uint64_t)eHdr->e_shentsize *
>> +					eHdr->e_shstrndx);
> Interesting, I had to solve a similar issue in Commit: 90240a79
> ("libcamera: media_device: prevent sign extension on casts"), which hit
> a real world issue causing breakage on the RPi when running a 32 bit
> userspace with a 64 bit kernel.
>
> I fear hitting more of those issues too, So I'm pleased to see these
> coverity warnings handled.
>
> In the patch I created, I ended up using uintptr_t as the cast, over the
> __u64 types which were already being used.
>
> Assuming that __u64 is similar to uint64_t, is there any key difference
> between uint64_t, and uintptr_t that means we should choose one over the
> other?

I am not sure. It seems to me that uintptr_t is a pointer cast that makes

it platform-independent/portable.

> At face value, they are both 64 bit values, though I guess actually
> uintptr_t is 'a value which stores a pointer or an integer' so it could
> be different in some cases.

Yes, both seem to end up being 64-bit but main issue I see is that, 
uintptr_t

seems to be used with casting of pointers, not actual data-type values. 
Here we have a struct

member containing the value that needs to be explicitly casted.

I am not sure if there is something similar to uintptr_t, but for values?

>
> Anyway, beyond the particular choice of cast destination, of which
> uint64_t is likely suitable in this case if it solves the issue, we
> should use C++ casts:
>
>    static_cast<uint64_t>(eHdr->e_shentsize) * ...
Ah correct. Was reading too much C code on stackoverflow for this :P
>
>
>
>
>>   	ElfW(Shdr) *sHdr = elfPointer<ElfW(Shdr)>(elf, offset);
>>   	if (!sHdr)
>>   		return {};
>> @@ -167,7 +168,8 @@ Span<uint8_t> elfLoadSymbol(Span<uint8_t> elf, const char *symbol)
>>   	/* Locate and return data of symbol. */
>>   	if (targetSymbol->st_shndx >= eHdr->e_shnum)
>>   		return {};
>> -	offset = eHdr->e_shoff + targetSymbol->st_shndx * eHdr->e_shentsize;
>> +	offset = eHdr->e_shoff + ((uint64_t)targetSymbol->st_shndx *
> C++ cast style here too
>
> With the casting corrected:
>
> Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
>
>> +				  eHdr->e_shentsize);
>>   	sHdr = elfPointer<ElfW(Shdr)>(elf, offset);
>>   	if (!sHdr)
>>   		return {};
>>


More information about the libcamera-devel mailing list