Using LD_PRELOAD wrappers to identify problem use of shared library functions
jakub at redhat.com
Thu Mar 10 17:05:03 UTC 2011
On Thu, Mar 10, 2011 at 11:25:38AM -0500, William Cohen wrote:
> Shared library are heavily used through Linux distributions.
> Unfortunately, there are cases of functions in the libraries having
> undefined behavior. Rather than immediately reporting the dependence on
> that undefined behavior, the applications may later fail in odd and
> seemingly random ways. On particular example of this problem is the
> memcpy function which has undefined behavior when the source and
> destination regions overlap. This resulted in the following bug being
> filled about "Strange sound on mp3 flash website":
> The diagnosis of this problem was not straightford because the memcpy
> silently corrupted the data in the copy. There are many other examples of
> this type of memcpy problems in bugzilla.
> What would be desirable is catching the dependency on undefined behavior
> when it occurs. The LD_PRELOAD environment variable allows wrappers for
> shared library functions to be inserted. These wrappers can do additional
> checks and flag those issues when they occur. The mutrace package in
> Fedora is one example of this approach. It makes use of this mechanism to
> instrument the mutex operations and can trigger a gdb breakpoint when a
> problem mutex operation occurs.
> I have taken the code in the mutrace package and made memstomp which looks
> for the memcpy of overlapping regions.
> git repo at:
> A fedora scratch package RPM at:
> Valgrind does check the arguments for memcpy (and many other memory
> related checks). The main advantage to using the specialized wrappers
> like memstomp is lower overhead. Most people are not willing to pay for
> the overhead that valgrind introduces (4x-100x slow downs). The overhead
> for the memstomp wrappers should be low enough that it would be feasible
> to set the LD_PRELOAD for Fedora alpha releases. This would make the
> problems depending on undefined behavior obvious rather than spending a
> large amount of time trying to replicate the problem and then diagnosing
Nice, but I think the dlsym (NULL, "main") lookup should not be done, at
least not by default, we really don't want to encourage people linking
programs with -rdynamic, that adds a runtime penalty.
And, it would be nice when you have such a library not to check just
memcpy, there are plenty of other commonly used calls which could
be warned about.
memcpy, strcpy, strncpy, strcat, strncat, strtok, strtok_r, mempcpy, strsep,
stpcpy, stpncpy, memccpy
just to name a few from <string.h>, then for -D_FORTIFY_SOURCE also
__memcpy_chk, __mempcpy_chk, __strcpy_chk, __stpcpy_chk, __strncpy_chk,
__stpncpy_chk, __strcat_chk, __strncat_chk.
In wchar.h e.g.
wcscpy, wcsncpy, wcscat, wcsncat, wcstok, wmemcpy, wmempcpy
mbrtowc, wcrtomb, mbrlen, mbsrtowcs, wcsrtombs, mbsnrtowcs,
wcsnrtombs, wcstol, wcstoul, wcstoll, wcstoull, ...
Maybe also sprintf/snprintf if format string contains some %s/%ls/%S
specifiers and those arguments overlap the target.
Basically, most of the __restrict/restrict qualified prototypes
in glibc headers would be good candidates for overlap tests (if possible
to determine length).
In the implementation of the checking library you probably want
to #include <sys/cdefs.h>, then #undef __restrict #define __restrict
and similarly for restrict and __restrict_arr and compile the
file with -fno-builtin, to make sure gcc doesn't optimize your checks
away based on the arguments being restricted pointers.
More information about the devel