Debugging memmove

From Wikitech

debug_memmove.c


#include <stdlib.h>
#include <stdio.h>

/* Version of memmove which aborts if a copy overruns the start of the frame
 * Based on the OpenSolaris implementation
 */

void *
memmove(void *s, const void *s0, size_t n)
{
        /*abort();*/

        if (n != 0) {
                char *s1 = s;
                const char *s2 = s0;
                /* Don't overwrite the frame */
                char * frame = (char*) __builtin_frame_address (1);
                if (s1 < frame && s1 + n >= frame) {
                        fprintf(stderr, "memmove(): attempt to overwrite the frame\n");
                        abort();
                }

                if (s1 <= s2) {
                        do {
                                *s1++ = *s2++;
                        } while (--n != 0);
                } else {
                        s2 += n;
                        s1 += n;
                        do {
                                *--s1 = *--s2;
                        } while (--n != 0);
                }
        }
        return (s);
}

test.c

#include <string.h>
#include <stdio.h>

int main(int argc, char** argv)
{
        char buffer1[100];
        char buffer2[100];
        printf("move 1... ");
        memmove(buffer1, buffer2, 50);
        printf("ok\n");
        memmove(buffer1, buffer2, 100000);
        printf("move 2... ");
        printf("ok\n");
        return 0;
}

Output

[0740][tstarling@zwinger:~/debug_memmove]$ gcc -c test.c
[0740][tstarling@zwinger:~/debug_memmove]$ gcc test.o debug_memmove.o -lc -o protected
[0740][tstarling@zwinger:~/debug_memmove]$ gcc test.c -o unprotected
[0740][tstarling@zwinger:~/debug_memmove]$ ./unprotected
move 1... ok
Segmentation fault
[0740][tstarling@zwinger:~/debug_memmove]$ ./protected
move 1... ok
memmove(): attempt to overwrite the frame
Aborted

Sample

Compiled -shared and LD_PRELOAD to load it into apache+php...

Program received signal SIGABRT, Aborted.
[Switching to Thread 46912497225344 (LWP 21075)]
0x0000003a5782e37d in raise () from /lib64/tls/libc.so.6
(gdb) bt
#0  0x0000003a5782e37d in raise () from /lib64/tls/libc.so.6
#1  0x0000003a5782faae in abort () from /lib64/tls/libc.so.6
#2  0x00002aaaaaaac7bb in memmove () from /usr/local/lib/debug/debug_memmove.x86_64.so
#3  0x00002aaaaadbf0f7 in zif_str_repeat () from /usr/local/apache/libexec/libphp5.so
#4  0x00002aaaaae5c84c in zend_do_fcall_common_helper_SPEC () from /usr/local/apache/libexec/libphp5.so
#5  0x00002aaaaae5c1a2 in execute () from /usr/local/apache/libexec/libphp5.so
#6  0x00002aaaaae5c430 in zend_do_fcall_common_helper_SPEC () from /usr/local/apache/libexec/libphp5.so
#7  0x00002aaaaae5c1a2 in execute () from /usr/local/apache/libexec/libphp5.so
#8  0x00002aaaaae5c430 in zend_do_fcall_common_helper_SPEC () from /usr/local/apache/libexec/libphp5.so
#9  0x00002aaaaae5c1a2 in execute () from /usr/local/apache/libexec/libphp5.so
#10 0x00002aaaaae5c430 in zend_do_fcall_common_helper_SPEC () from /usr/local/apache/libexec/libphp5.so
#11 0x00002aaaaae5c1a2 in execute () from /usr/local/apache/libexec/libphp5.so
#12 0x00002aaaaae5c430 in zend_do_fcall_common_helper_SPEC () from /usr/local/apache/libexec/libphp5.so
#13 0x00002aaaaae5c1a2 in execute () from /usr/local/apache/libexec/libphp5.so
#14 0x00002aaaaae5c430 in zend_do_fcall_common_helper_SPEC () from /usr/local/apache/libexec/libphp5.so
#15 0x00002aaaaae5c1a2 in execute () from /usr/local/apache/libexec/libphp5.so
#16 0x00002aaaaae5c430 in zend_do_fcall_common_helper_SPEC () from /usr/local/apache/libexec/libphp5.so
#17 0x00002aaaaae5c1a2 in execute () from /usr/local/apache/libexec/libphp5.so
#18 0x00002aaaaae5c430 in zend_do_fcall_common_helper_SPEC () from /usr/local/apache/libexec/libphp5.so
#19 0x00002aaaaae5c1a2 in execute () from /usr/local/apache/libexec/libphp5.so
#20 0x00002aaaaae5c430 in zend_do_fcall_common_helper_SPEC () from /usr/local/apache/libexec/libphp5.so
#21 0x00002aaaaae5c1a2 in execute () from /usr/local/apache/libexec/libphp5.so
#22 0x00002aaaaae71ead in ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER () from /usr/local/apache/libexec/libphp5.so
#23 0x00002aaaaae5c1a2 in execute () from /usr/local/apache/libexec/libphp5.so
#24 0x00002aaaaae3de67 in zend_execute_scripts () from /usr/local/apache/libexec/libphp5.so
#25 0x00002aaaaadfeecf in php_execute_script () from /usr/local/apache/libexec/libphp5.so
---Type <return> to continue, or q <return> to quit---
#26 0x00002aaaaaeb4a7f in apache_php_module_main () from /usr/local/apache/libexec/libphp5.so
#27 0x00002aaaaaeb547f in send_php () from /usr/local/apache/libexec/libphp5.so
#28 0x00002aaaaaeb572f in send_parsed_php () from /usr/local/apache/libexec/libphp5.so
#29 0x00000000004315d4 in ap_invoke_handler (r=0x759a00) at http_config.c:475
#30 0x0000000000448ad6 in process_request_internal (r=0x759a00) at http_request.c:1298
#31 0x0000000000448b2b in ap_process_request (r=0x759a00) at http_request.c:1314
#32 0x000000000043f191 in child_main (child_num_arg=12) at http_main.c:4786
#33 0x000000000043f460 in make_child (s=0x5b10b0, slot=12, now=1140162878) at http_main.c:4956
#34 0x000000000043f80d in perform_idle_server_maintenance () at http_main.c:5141
#35 0x000000000043fe32 in standalone_main (argc=2, argv=0x7fffffe3e718) at http_main.c:5404
#36 0x0000000000440412 in main (argc=2, argv=0x7fffffe3e718) at http_main.c:5657
(gdb)