Glibc-memlap

John Reiser jreiser BitWagon com

BitWagon Software LLC

November 28, 2010

revised November 30, 2010



This experimental patch implements one way for glibc to detect, diagnose, and work around the bug of specifying overlapping source and destination regions in a call to memcpy or mempcpy. If the environment variable MEMCPY_CHECK_ [note the trailing underscore] exists and is non-zero, then glibc will detect these errors. If the value is odd, then a diagnostic message is printed to stderr (file descriptor 2). The higher-order bits are a counter of the number of errors which are allowed before glibc forcibly terminates execution. If actual overlap occurs, then the patch implements the operation using memmove instead of memcpy or mempcpy. The work-around produces defined behavior which the programmer probably intended, instead of the undefined behavior that is allowed by the C language.

Environment variable

Overlap in memcpy/mempcpy

Unset

No detection

MEMCPY_CHECK_=0

No detection

MEMCPY_CHECK_=1

Detect; print a message on stderr; abort

MEMCPY_CHECK_=10

Detect; no print; skip 5 instances before abort

MEMCPY_CHECK_=51

Detect; print; abort on 26th instance



The diagnostic message looks like:

*** memcpy overlap @0x8050267 (0x401250, 0x401253, 0x5) ***

which lists the return address and parameter values. The same text is used for mempcpy.

The patch implements this feature by extending the internal function __init_cpu_features to take a parameter getenv. This requires passing getenv as the first parameter to each STT_GNU_IFUNC indirect function. Thus some of the “CPU” features may be controlled by the software environment as well as by the hardware. When the implementation is selected for memcpy, then a non-zero MEMCPY_CHECK_ chooses the code which checks for overlap.

Detecting no overlap costs about 4 or 5 CPU cycles per call to memcpy or mempcpy. If overlap exists, then overhead and redirecting execution to memmove costs on the order of 100 cycles. The diagnostic message costs a couple hundred cycles plus the write() system call.

The present implementation supports x86_64 and i686 only. Other architectures are possible but not implemented due to not enough programmer time and resources for testing.

The getenv that is passed to a STT_GNU_IFUNC indirect function is the runtime loader's (rtld: ld-linux) getenv. At the beginning of execution (immediately after execve) this is equivalent to libc's getenv. However, calling putenv may cause the two subroutines to diverge. Specify what you want before execve; do not rely on some initialization function setting MEMCPY_CHECK_.



Downloads (based on Fedora 15 rawhide):

File

Length

Md5sum

memcpy-overlap.patch

96828

be86b7882356b79197ff8546e4f49cd5

strcmp-cond-brace.patch

36483

a83546adc996ab2aaeb4cd2235956bdf

glibc-memlap-2.12.90-19.i686.rpm

6080555

2b3edb00e3a330e5312a94617d6b8ec7

glibc-memlap-2.12.90-19.x86_64.rpm

5562284

ca8c3d5d30ead1e89c0f8e9a61156bf7

glibc-memlap-2.12.90-19.src.rpm

11516311

b3cf7048b7abc08cc586cfa4002c8505




glibc-common-2.12.90-19.i686.rpm

27058162

25af93e0d72434c7ddf3718db8e200ea

glibc-common-2.12.90-19.x86_64.rpm

27087972

b9fb6da52a7de89b2be3c33053f2dd88

glibc-debuginfo-2.12.90-19.i686.rpm

25435861

ef98f4d51a8cfe9f10f4b1ed26188910

glibc-debuginfo-2.12.90-19.x86_64.rpm

24962716

e93abdd639762d642746f9573e28d404

glibc-devel-2.12.90-19.i686.rpm

1045424

dc1dc28473545b971eed4936b3df93b4

glibc-devel-2.12.90-19.x86_64.rpm

1044539

0df617d8a42aa5ef4e55e9291ba7645b

glibc-headers-2.12.90-19.i686.rpm

662823

3c775922d4150951c29ccba62103122e

glibc-headers-2.12.90-19.x86_64.rpm

653431

75de90c5515a89ac66b06d3ddad1e6c5

glibc-static-2.12.90-19.i686.rpm

1416669

3b5e5acb39a92fd804c716fa0721017b

glibc-static-2.12.90-19.x86_64.rpm

1827595

76f5a7267bebac7520128b2ca663d218

glibc-utils-2.12.90-19.i686.rpm

166694

0c3d30a47956310ff40fbe7e26cf1264

glibc-utils-2.12.90-19.x86_64.rpm

165770

1aaeb9b4f78f509cde168a260f5be88b

nscd-2.12.90-19.i686.rpm

216204

e7e15d4d9dda4bf5c59edad5bfbf4473

nscd-2.12.90-19.x86_64.rpm

218869

7fe5c28802582fbd2f1a6ec28ce042bc