SEGV signal handling bug (dynamic linking)
Hi,
Don't know if anyone expects this to work yet or not, but:
------------------------- cut ----------------------------- #include <sys/ptrace.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/mman.h>
char *mem;
void sig_handler(int sig)
{
int res;
printf("Trapped!!!\n");
res = mprotect(mem, 4096, PROT_READ|PROT_WRITE);
if (res < 0) {
perror("mprotect");
exit(1);
}
}void install_handlers(void)
{
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = sig_handler;
sigaction(SIGSEGV, &act, NULL);
}int main(int argc, char **argv)
{
int res;
mem = malloc(8192);
if (mem == NULL) {
perror("malloc");
exit(1);
}
mem = (char *)(((int)mem + 4095) & ~0x0fff);
res = mprotect(mem, 4096, PROT_READ);
if (res < 0) {
perror("mprotect");
exit(1);
}
install_handlers();
write(1, "Going\n", 6);
mem[24] = 17;
write(1, "Gone\n", 5);
return 0;
}------------------------- cut -----------------------------
generates:
Going
Bus error
plus the following on the console:
do_page_fault() pid=167 command='ch'
YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI
PSW: 00000000000001001111111100001011
r0-3 00000000 fffff000 0000166f 00002944 r4-7 40138c38 2001fd8c 00002852 00000001 r8-11 00002862 0008b010 0009c290 0009cbf0 r12-15 00000000 00000000 0009cb50 00000000 r16-19 00000000 00000001 0000b71b 00000011 r20-23 00004000 40041fcc 40041fcc 00000008 r24-27 00000006 00001000 00000001 0000280c r28-31 00000006 00000020 20020140 40041fd7 sr0-4 00000000 00000003 00000000 0000000a sr4-8 0000000a 0000000a 0000000a 0000000a
IASQ: 0000000a 0000000a IAOQ: 0000167b 0000167f
IIR: 6293002e ISR: 0000000a IOR: 00004017ORIG_R28: 00002880
!!die_if_kernel: ch(167): Unaligned data reference 28
YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI
PSW: 00000000000011001111111100001011
r0-3 00000000 fffff000 20020140 00002944 r4-7 40138c38 2001fd8c 00002852 00000001 r8-11 00002862 0008b010 0009c290 0009cbf0 r12-15 00000000 00000000 0009cb50 00000000 r16-19 00000000 00000001 0000b71b 00000000 r20-23 0000289f 40041fcc 40041fcc 00000008 r24-27 200201d0 20020150 0000000b 0000280c r28-31 00000006 00000020 200203c0 40041fd7 sr0-4 00000000 00000003 00000000 0000000a sr4-8 0000000a 0000000a 0000000a 0000000a
IASQ: 0000000a 0000000a IAOQ: 0000289b 0000289b
IIR: 0e801096 ISR: 0000000a IOR: 0000289fORIG_R28: 00002880
The first do_page_fault() is fine, it is the 'mem[24] = 17' line, but the second isn't. The corresponding code is at the end of .plt:
2898: 0e 80 10 96 ldw 0(sr0,r20),r22
289c: ea c0 c0 00 bv r0(r22)
28a0: 0e 88 10 95 ldw 4(sr0,r20),r21
28a4: ea 9f 1f dd b,l 2898 <__DTOR_END__+0x74>,r20
28a8: d6 80 1c 1e depwi 0,31,2,r20
28ac: 00 c0 ff ee # c0ffee
28b0: de ad be ef #deadbeefHowever, if I make it statically linked, it works fine, giving:
Going
Trapped!!!
Gone
Richard
Quoted 7 lines · Richard Hirst
mem = malloc(8192);
if (mem == NULL) {
perror("malloc");
exit(1);
}
mem = (char *)(((int)mem + 4095) & ~0x0fff);
res = mprotect(mem, 4096, PROT_READ);Read the Unix standard:
The behavior of this function is unspecified if the mapping was not established by a call to mmap().
Signature · 3 lines
---------------. ,-. 1325 Chesapeake Terrace Ulrich Drepper \ ,-------------------' \ Sunnyvale, CA 94089 USA Red Hat `--' drepper at redhat.com `------------------------
Quoted 10 lines · Ulrich Drepper
Quoted 7 lines · Richard Hirst
mem = malloc(8192); if (mem == NULL) { perror("malloc"); exit(1); } mem = (char *)(((int)mem + 4095) & ~0x0fff); res = mprotect(mem, 4096, PROT_READ);
Quoted 4 lines
Read the Unix standard:
The behavior of this function is unspecified if the mapping was not established by a call to
mmap().
Yeh, but it works on m68k and i386, and works on hppa if statically linked. And the code is in an example on the mprotect man page on my Mandrake7 box.
Richard
Quoted 3 lines · Richard Hirst
Yeh, but it works on m68k and i386, and works on hppa if statically linked. And the code is in an example on the mprotect man page on my Mandrake7 box.
Then shoot the guy who wrote the man page. It's wrong and will never reliably work.
Signature · 3 lines
---------------. ,-. 1325 Chesapeake Terrace Ulrich Drepper \ ,-------------------' \ Sunnyvale, CA 94089 USA Red Hat `--' drepper at redhat.com `------------------------
Quoted 10 lines · Ulrich Drepper
Quoted 7 lines · Richard Hirst
mem = malloc(8192); if (mem == NULL) { perror("malloc"); exit(1); } mem = (char *)(((int)mem + 4095) & ~0x0fff); res = mprotect(mem, 4096, PROT_READ);
Quoted 4 lines
Read the Unix standard:
The behavior of this function is unspecified if the mapping was not established by a call to
mmap().
Changed my prog to use mmap and get the same problem.
Richard