It looks like memmove() is broken by design for mips. This has come up
before in a previous thread, but with no proper resolution:
https://mailman.uclibc-ng.org/pipermail/devel/2016-April/000837.html
Per the man pages and posix specification, memmove() must work with
overlapping regions:
https://linux.die.net/man/3/memmove
https://www.unix.com/man-page/POSIX/3posix/memmove/
Unless __ARCH_HAS_BWD_MEMCPY__ is set, the generic memmove() (which is
used for mips) will use memcpy() when the destination pointer is lower
than the source pointer, whether the regions are overlapping or not.
The author of libc/string/mips/memcpy.S is clear about the fact that
the mips implementation for memcpy() cannot deal with overlapping
regions. For Android, support for overlapping regions seems to be
required for memcpy(), so memcpy() will offload to memmove() when an
overlap occurs. How this could work with memmove() again offloading to
memcpy() on mips is lost on me.
I am observing the problem on a big-endian mips 34kc with OpenSSL. We
are using nginx as an https webserver with openssl as the ssl library.
We observed unexpected Message Authentication Code failures when data
was received.
After some detective work, we were observing the uClibc memmove()
occasionally copying a source buffer cache-line worth of zero's (32
bytes) to the destination buffer instead of the actual source data.
Needless to say, I do not know of a cipher that plays nicely when the
input buffer suffers from Alzheimer's. The OpenSSL implementation of
the GCM-128 cipher rightfully fails the tag check from it's perspective,
returning a Message Authentication Code failure to the client.
I quick solution is to always define __ARCH_HAS_BWD_MEMCPY__ on mips,
but I do not consider that a clear expression of the intent.
Can anyone comment on this?
- Pieter Smith