Mailing List Archive

pointer subtraciton on arm for 8.3p1
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?

Sandy Patterson

P.S. My backtrace looks like this:
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1 0xb6b84600 in __GI_abort () at abort.c:79
#2 0x7f715c00 in __subvsi3 (a=<optimized out>, b=<optimized out>) at
../../../gcc-7-20180201/libgcc/libgcc2.c:119
#3 0x7f713494 in strlcpy (
dst=0x7fff2428
"ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521",
src=0x7ffffec0
"ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521",
siz=393) at strlcpy.c:55
#4 0x7f6d4860 in xstrdup (
str=0x7ffffec0
"ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521")
at xmalloc.c:94
#5 0x7f6c6ee4 in match_list (
client=0x7ffffec0
"ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521",
server=0x7fff9e90 "sk-ecdsa-sha2-nistp256@openssh.com", next=0x0)
at match.c:277
#6 0x7f6e9a70 in kex_names_cat (
a=0x7ffffd30
"ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521",
b=0x7fff15f8 "sk-ecdsa-sha2-nistp256@openssh.com")
at kex.c:200
#7 0x7f6e9e08 in kex_assemble_names (listp=0x7f75b364 <options+1188>,
def=0x7ffded88
"ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,sk-ecdsa-sha2-nistp256@openssh.com,ssh-ed25519,sk-ssh-ed25519@openssh.com,rsa-sha2-512,rsa-sha2-256,ssh-rsa",
all=0x7fffa470
"ssh-ed25519,ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,ssh-rsa,rsa-sha2-256,rsa-sha2-512,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,sk-ecdsa-sha2-nistp256@openssh.com,ssh-rsa-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,sk-ecdsa-sha2-nistp256-cert-v01@openssh.com")
at kex.c:291
#8 0x7f663964 in assemble_algorithms (o=0x7f75aec0 <options>) at servconf.c:229
#9 0x7f66ba44 in copy_set_server_options (dst=0x7f75aec0 <options>,
src=0xbecbf3a8, preauth=0) at servconf.c:2546
#10 0x7f66a418 in parse_server_match_config (options=0x7f75aec0
<options>, includes=0x7f759050 <includes>, connectinfo=0x7f759b10
<ci>) at servconf.c:2428
#11 0x7f6721ac in getpwnamallow (ssh=0x7fff8a88, user=0x7ffeeab0
"root") at auth.c:575
#12 0x7f688d34 in mm_answer_pwnamallow (ssh=0x7fff8a88, sock=6,
m=0x7fffa1e8) at monitor.c:732
#13 0x7f687f40 in monitor_read (ssh=0x7fff8a88, pmonitor=0x7ffef670,
ent=0x7f759644 <mon_dispatch_proto20+24>, pent=0xbecc0648) at
monitor.c:522
#14 0x7f68720c in monitor_child_preauth (ssh=0x7fff8a88,
pmonitor=0x7ffef670) at monitor.c:304
#15 0x7f65a9fc in privsep_preauth (ssh=0x7fff8a88) at sshd.c:512
#16 0x7f660a4c in main (ac=3, av=0x7ffdb160) at sshd.c:2183
_______________________________________________
openssh-unix-dev mailing list
openssh-unix-dev@mindrot.org
https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev
Re: pointer subtraciton on arm for 8.3p1 [ In reply to ]
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
_______________________________________________
openssh-unix-dev mailing list
openssh-unix-dev@mindrot.org
https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev
Re: pointer subtraciton on arm for 8.3p1 [ In reply to ]
Hi Damien,

Thanks for the suggestions. It seems someone beat me to the gcc bug:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81801
There are quite a lot of referenced bugs and it seems pointer subtraction over
the boundary is a tricky problem.

This one mentions other compilers doing similar things:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63303

There doesn't appear to be any resolution to the openssh bug, and they filed
it against gcc8. Something breaks on our system in gcc8+ so I don't
think i can test further
there.

-fwrapv does seem like a good workaround for us and it solves my
problem. I don't know
autotools well enough to propose a patch that sets this when necessary
and i'm not sure
you'd consider one anyway.

Sandy



On Thu, Jun 11, 2020 at 10:33 PM Damien Miller <djm@mindrot.org> wrote:
>
> 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
_______________________________________________
openssh-unix-dev mailing list
openssh-unix-dev@mindrot.org
https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev