[libcamera-devel] [PATCH] libcamera: ipa_module: Fix implicit sign-extension in eflLoadSymbol
Kieran Bingham
kieran.bingham at ideasonboard.com
Fri Jun 5 10:01:12 CEST 2020
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?
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.
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) * ...
> 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 {};
>
--
Regards
--
Kieran
More information about the libcamera-devel
mailing list