I''m doing research into stack monitoring and have made a simple server that has the following method: int handle_reply(char *str){ char response[256]; strcpy(response,str); printf("The client says \"%s\"\n",response); return 0; } I''m overflowing this with 300 bytes of the letter ''A''. I''m verifying with gdb that the eip register contains the hex value for ''A'' (0x41) but when i print out the value of eip in dtrace with uregs[R_EIP] on function return, it is still the original return address, not 0x41414141. The program is seg faulting so i know the eip is being overwritten but obviously i''m not using dtrace correctly in this case. I''m under the impression that uregs[] holds the values of the registers on the stack for the pocess it is instrumenting. I''m not exactly sure of how dtrace is implemented but i''m thinking dtrace should be copying the value of the eip register into a local buffer when the above function returns and therefore should have the value 0x41414141 since it has already been overwritten with that value. Dtrace does return the value 0x41414141 for the ebp register though, which is what i expected. Should the value of uregs[R_EIP] not also be 0x41414141? Any help on this would be appreciated. -- This message posted from opensolaris.org
Can you send the DTrace invocation that you''re using, please? Adam On Sun, Mar 23, 2008 at 09:16:25PM -0700, bryan wrote:> I''m doing research into stack monitoring and have made a simple server that has the following method: > > int handle_reply(char *str){ > char response[256]; > > strcpy(response,str); > > printf("The client says \"%s\"\n",response); > > return 0; > } > > I''m overflowing this with 300 bytes of the letter ''A''. I''m verifying with gdb that the eip register contains the hex value for ''A'' (0x41) but when i print out the value of eip in dtrace with uregs[R_EIP] on function return, it is still the original return address, not 0x41414141. The program is seg faulting so i know the eip is being overwritten but obviously i''m not using dtrace correctly in this case. I''m under the impression that uregs[] holds the values of the registers on the stack for the pocess it is instrumenting. I''m not exactly sure of how dtrace is implemented but i''m thinking dtrace should be copying the value of the eip register into a local buffer when the above function returns and therefore should have the value 0x41414141 since it has already been overwritten with that value. Dtrace does return the value 0x41414141 for the ebp register though, which is what i expected. Should the value of uregs[R_EIP] not also be 0x41414141? > > Any help on this would be appreciated. > > > -- > This message posted from opensolaris.org > _______________________________________________ > dtrace-discuss mailing list > dtrace-discuss at opensolaris.org-- Adam Leventhal, Fishworks http://blogs.sun.com/ahl
Here is the latest script that I used just so i could see the values at both entry and return for both handle_reply and strcpy: ----------------------------- #!/usr/sbin/dtrace -s pid$1::handle_reply:entry { printf("\nEBP=%x EIP=%x\n", uregs[R_EBP], uregs[R_EIP]); } pid$1::strcpy:entry { printf("\nEBP=%x EIP=%x\n", uregs[R_EBP], uregs[R_EIP]); } pid$1::strcpy:return { printf("\nEBP=%x EIP=%x\n", uregs[R_EBP], uregs[R_EIP]); } pid$1::handle_reply:return { printf("\nEBP%x EIP=%x\n", uregs[R_EBP], uregs[R_EIP]); } ----------------------- I literally just ran the script below though and i''m getting both registers showing 0x41414141: -------------------------- #!/usr/sbin/dtrace -s fbt::strcpy:return / pid == $1 / { printf("Buffer overflow: eip=%x ebp=%x\n", uregs[R_EIP], uregs[R_EBP]); } ------------------------- with this output: CPU ID FUNCTION:NAME 1 22691 strcpy:return Buffer overflow: eip=fedc5b35 ebp=8045f4c 0 22691 strcpy:return Buffer overflow: eip=41414141 ebp=41414141 0 22691 strcpy:return Buffer overflow: eip=41414141 ebp=41414141 0 22691 strcpy:return Buffer overflow: eip=41414141 ebp=41414141 0 22691 strcpy:return Buffer overflow: eip=41414141 ebp=41414141 ^C Though i''m a little confused on this output, especially the first line and the multiple outputs for a program that seg faulted. I''ve been focusing on the pid provider too much i guess, I would still like to know what i''m doing wrong on the pid provider or what the difference is as to why it doesn''t report the same back. Thanks for the time and help. -- This message posted from opensolaris.org
This is interesting, when i run this script: fbt::strcpy:entry / pid == $1 / { self->eip = uregs[R_EIP]; printf("EIP=%x", self->ebp); } fbt::strcpy:return / pid == $1 / { printf("saved EIP=%x return EIP=%x", self->eip, uregs[R_EIP]); } produces this output: dtrace: script ''./registers.d'' matched 2 probes CPU ID FUNCTION:NAME 1 22690 strcpy:entry EIP=fedc5b35 1 22691 strcpy:return saved EIP=fedc5b35 return EIP=fedc5b35 0 22690 strcpy:entry EIP=41414141 0 22691 strcpy:return saved EIP=41414141 return EIP=41414141 0 22690 strcpy:entry EIP=41414141 0 22691 strcpy:return saved EIP=41414141 return EIP=41414141 0 22690 strcpy:entry EIP=41414141 0 22691 strcpy:return saved EIP=41414141 return EIP=41414141 0 22690 strcpy:entry EIP=41414141 0 22691 strcpy:return saved EIP=41414141 return EIP=41414141 the strcpy commnad is only called once in the program but is entered according to dtrace multiple times. Can anyone explain what is going on here? -- This message posted from opensolaris.org
Hi,> fbt::strcpy:entry[...]> fbt::strcpy:return[...]> the strcpy commnad is only called once in the programYou are using probes in kernel function "strcpy" and you are running userland program using strcpy(3C) function. These two do not have anything in common. Maybe you would want to use pid provider? dtrace -n ''pid$target::strcpy:entry{ustack()}'' -c pwd dtrace: description ''pid$target::strcpy:entry'' matched 2 probes /home/vm156888 dtrace: pid 8982 has exited CPU ID FUNCTION:NAME 1 73860 strcpy:entry ld.so.1`strcpy ld.so.1`expand+0x937 ld.so.1`expand_paths+0x139 ld.so.1`_elf_lookup_filtee+0x1a4 ld.so.1`elf_lookup_filtee+0x70 ld.so.1`elf_find_sym+0x26f ld.so.1`core_lookup_sym+0x71 ld.so.1`_lookup_sym+0x263 ld.so.1`lookup_sym+0xf9 ld.so.1`elf_bndr+0x103 ld.so.1`elf_rtbndr+0x14 0xfeff0458 ld.so.1`rt_thr_init+0x35 ld.so.1`setup+0xfe7 ld.so.1`_setup+0x2e9 ld.so.1`_rt_boot+0x56 0x8046718 I''m sorry if I misunderstood your question. -- Vlad -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 193 bytes Desc: not available URL: <http://mail.opensolaris.org/pipermail/dtrace-discuss/attachments/20080326/b6d0c6c3/attachment.bin>
Since you''re using the fbt provider rather than the pid provider you''re seeing the calls to strcpy() in the kernel as a result of the program dumping core. As for why you''re seeing the old program counter, the D program effectively executes after the other effects of the instruction have been processed, but before the program counter has advanced. This is by design so that tracing the program counter or stack trace matches the location at which the probe was placed. Adam On Wed, Mar 26, 2008 at 09:49:21AM -0700, bryan wrote:> This is interesting, when i run this script: > > fbt::strcpy:entry > > / pid == $1 / > { > self->eip = uregs[R_EIP]; > printf("EIP=%x", self->ebp); > } > > fbt::strcpy:return > > / pid == $1 / > { > printf("saved EIP=%x return EIP=%x", self->eip, uregs[R_EIP]); > } > > produces this output: > > dtrace: script ''./registers.d'' matched 2 probes > CPU ID FUNCTION:NAME > 1 22690 strcpy:entry EIP=fedc5b35 > 1 22691 strcpy:return saved EIP=fedc5b35 return EIP=fedc5b35 > 0 22690 strcpy:entry EIP=41414141 > 0 22691 strcpy:return saved EIP=41414141 return EIP=41414141 > 0 22690 strcpy:entry EIP=41414141 > 0 22691 strcpy:return saved EIP=41414141 return EIP=41414141 > 0 22690 strcpy:entry EIP=41414141 > 0 22691 strcpy:return saved EIP=41414141 return EIP=41414141 > 0 22690 strcpy:entry EIP=41414141 > 0 22691 strcpy:return saved EIP=41414141 return EIP=41414141 > > the strcpy commnad is only called once in the program but is entered according to dtrace multiple times. Can anyone explain what is going on here? > > > -- > This message posted from opensolaris.org > _______________________________________________ > dtrace-discuss mailing list > dtrace-discuss at opensolaris.org-- Adam Leventhal, Fishworks http://blogs.sun.com/ahl
On Wed, Mar 26, 2008 at 02:25:10PM -0700, Adam Leventhal wrote:> As for why you''re seeing the old program counter, the D program effectively > executes after the other effects of the instruction have been processed, but > before the program counter has advanced. This is by design so that tracing the > program counter or stack trace matches the location at which the probe was > placed.I found a reference to a DTrace script which seems to have worked in the way that you had anticipated by expecting to the see the value of the program counter after the ret instruction had executed. Looking into this a bit more, I changed this behavior in March 2005 to fix this bug: 6236726 ustack() at pid provider return probes can be confusing There''s an existing RFE to expose the true value of the traced instruction: 5106439 pidprovider instrumentation obscures original instruction It would be a good idea to also expose the pending program counter update. Adam -- Adam Leventhal, Fishworks http://blogs.sun.com/ahl