glibc detected freeing invalid pointer on ash... might be a bug, but I'm not sure
Denis Vlasenko
vda.linux at googlemail.com
Thu Mar 15 00:39:05 UTC 2007
Hi,
Thanks for your effort.
On Wednesday 14 March 2007 02:29, Franklin wrote:
> I got some free time today and dig ash.c more.
>
> I found that the mark->stackp was always cleared to NULL at this point:
>
> evalbltin():
> if ((i = setjmp(jmploc.loc)))
> goto cmddone;
>
> You can see the log file attached in this mail. I passed the &smark to
> evalbltin(), and print the mark and mark->stackp value. You can search for
> keywork "(nil)", and you can find that it was always cleared to NULL after
> calling setjmp().
setjmp is "magic". It marks the point (CPU state) to which you
can return later with longjmp (by reloading CPU state into CPU).
(more info on their manpages)
However, this does not explain how mark->stackp managed to
mysteriously change to NULL here:
evalbltin 2: mark=0x7fe7b890, mark->stackp=0x100821a8. call setjmp(jmploc.loc)
evalbltin 4: mark=0x7fe7b890, mark->stackp=(nil)
The code:
fprintf(stderr, "evalbltin 2: mark=%p, mark->stackp=%p. call setjmp(jmploc.loc)\n", mark, mark->stackp);
if ((i = setjmp(jmploc.loc))) {
fprintf(stderr, "evalbltin 3: mark=%p, mark->stackp=%p. i=%d, goto cmddone\n", mark, mark->stackp, i);
goto cmddone;
}
savehandler = handler;
fprintf(stderr, "evalbltin 4: mark=%p, mark->stackp=%p\n", mark, mark->stackp);
If setjmp returned 0, it means that no jump occurred. setjmp just
saved CPU state to jmploc.loc, if() didn't trigger and you arrived to '4'.
But why this changed mark->stackp???
This is really strange. Can you do
make shell/ash.s
objdump -dr shell/ash.o
and also
objdump -dr busibox_unstripped if you do static build.
I'm interested in setjmp assembly. For example, mine is:
080543f8 <_setjmp>:
80543f8: 31 c0 xor %eax,%eax
80543fa: 8b 54 24 04 mov 0x4(%esp),%edx
80543fe: 89 1a mov %ebx,(%edx)
8054400: 89 72 04 mov %esi,0x4(%edx)
8054403: 89 7a 08 mov %edi,0x8(%edx)
8054406: 8d 4c 24 04 lea 0x4(%esp),%ecx
805440a: 89 4a 10 mov %ecx,0x10(%edx)
805440d: 8b 0c 24 mov (%esp),%ecx
8054410: 89 4a 14 mov %ecx,0x14(%edx)
8054413: 89 6a 0c mov %ebp,0xc(%edx)
8054416: 89 42 18 mov %eax,0x18(%edx)
8054419: c3 ret
805441a: 90 nop
805441b: 90 nop
What I am trying to understand - whether setjmp corrupts
mark->stackp by using wrong stack slot (fetching mark and using
it as a pointer to something else).
Indirect way to test this theory:
struct stackmark {
+ char BOGOBUFFER[16];
struct stack_block *stackp;
char *stacknxt;
size_t stacknleft;
struct stackmark *marknext;
};
This will make stackp inaccessible by just storing a word at *mark.
Thanks!
--
vda
More information about the busybox
mailing list