pointer subtraciton on arm for 8.3p1

Damien Miller djm at mindrot.org
Fri Jun 12 12:33:47 AEST 2020


On Thu, 11 Jun 2020, Sandy Patterson wrote:

> I use OpenSSH server on an embedded arm using GCC7 cross toolchain. I
> found that spamming connection attempts sometimes causes aborts in
> sshd. Upon getting this up in gdb I found that the pointer subtraction
> inside openbsd-compat/{strlcat.c,strlcpy.c} (and maybe elsewhere)
> causes the 32 bit pointer difference to wrap which triggers the abort
> because of the -ftrapv option.
> 
> This example illustrates the problem, I get an abort when I compile
> for 32 bit arm.
> 
> > #include <stdio.h>
> > int main(int argc, char** argv) {
> >     char* src = (char*)0x7ffffec0;
> >     char* s = (char*)0x80000049;
> >     printf("%ld\n",s - src);
> >     return 0;
> > }
> 
> 
> inside the strlcpy.c for example we have:
> > return(s - src - 1); /* count does not include NUL */
> 
> It is somewhat infrequent as the array has to straddle the 0x80000000 boundary.
> 
> I can clearly disable hardening or hack out ftrapv from my system, but
> was wondering if you guys have some advice on how to fix openssh for
> this platform?

Your compiler might be broken. C11 s6.5.6/9 says that pointer
subtraction should work so long as 1) the pointers are to the same array
object and 2) the difference must be representable in a ptrdiff_t. In
this case, AFAIK both conditions are true (the pointers relate to the same
array and the difference is <2^31).

Now, I'm not sure whether the compiler problem is limited to ftrapv
or is actually worse. Signed over/underflow is AFAIK undefined behaviour
and the compiler is allowed to do all sorts of crazy stuff when it is
encountered (including optimising away checks and creating security
problems, e,g, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=30475)

I'd suggest filing a gcc bug, and then trying a newer gcc or perhaps a
recent clang, but I understand what a hassle that can be on embedded
platforms.

If you can't do this, then I'd recommend compiling *everything* with
-fwrapv, that at least should remove the undefined behaviour element
here. FWIW, OpenBSD makes -fwrapv the default in its toolchain.

-d


More information about the openssh-unix-dev mailing list