This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[RFC][PATCH] Avoid mempcpy/ifunc in __libc_message
- From: "Maciej W. Rozycki" <macro at codesourcery dot com>
- To: <libc-alpha at sourceware dot org>
- Date: Wed, 25 Sep 2013 16:03:56 +0100
- Subject: [RFC][PATCH] Avoid mempcpy/ifunc in __libc_message
- Authentication-results: sourceware.org; auth=none
Hi,
I have been investigating an elf/ifuncmain5picstatic test case failure:
unexpected reloc type in static binarySegmentation fault
-- the immediate cause is I believe a bug in binutils that makes an empty
(R_*_NONE) reloc to appear in the static binary, however what's concerned
me is the segmentation fault that follows. I don't think our code should
ever crash even if supplied with unexpected/wrong data.
I have tracked down the cause to be a call to mempcpy made in
__libc_message -- mempcpy calls memcpy on this target and that happens to
be an ifunc (as one of the usual suspects). As the `reloc type' failure
happens in ifunc processing the pointer to memcpy directs control to the
ifunc resolver that would be used in the dynamic case rather than a memcpy
implementation and the final address of the memcpy variant chosen is
returned rather than the value of the `to' pointer (and memcpy executed).
As a result further code in __libc_message that uses the pointer returned
tries to poke at the read-only text segment and crashes.
I have tried to address it with the change below that replaces the call
to mempcpy with an equivalent handcoded sequence (I don't think
performance is critical here), however that does not save the program from
crashing later on, in raise (SIGABRT) that wants to access the TLS, that
hasn't been initialised at that stage yet. I see no immediate solution to
this problem and will appreciate ideas.
What can we do to avoid accessing bits that haven't been initialised this
early on this failure path? I think it's important that the failure path
is robust so as to be usable for diagnostics, which means error reporting
and process termination should not rely on anything that requires run-time
initialisation. Even the removal of this particular call to mempcpy I
find fragile as there isn't really anything that could guarantee none of
the other calls that occur in the failure path are not ifuncs on any
target.
Any thoughts?
2013-09-25 Maciej W. Rozycki <macro@codesourcery.com>
* sysdeps/posix/libc_fatal.c (__libc_message): Avoid a call to
mempcpy.
Maciej
glibc-libc-message-noifunc.diff
Index: glibc-fsf-trunk-quilt/sysdeps/posix/libc_fatal.c
===================================================================
--- glibc-fsf-trunk-quilt.orig/sysdeps/posix/libc_fatal.c 2013-04-19 23:05:52.467439498 +0100
+++ glibc-fsf-trunk-quilt/sysdeps/posix/libc_fatal.c 2013-09-25 15:35:36.927953246 +0100
@@ -151,8 +151,11 @@ __libc_message (int do_abort, const char
{
buf->size = total;
char *wp = buf->msg;
+ const char *rp;
+ size_t i;
for (int cnt = 0; cnt < nlist; ++cnt)
- wp = mempcpy (wp, iov[cnt].iov_base, iov[cnt].iov_len);
+ for (i = iov[cnt].iov_len, rp = iov[cnt].iov_base; i--; )
+ *wp++ = *rp++;
*wp = '\0';
/* We have to free the old buffer since the application might