Date: Thu, 13 Oct 2005 21:30:23 GMT From: Nate Eldredge <nge@cs.hmc.edu> To: freebsd-bugs@FreeBSD.org Subject: Re: bin/45478: /bin/sh coredump Message-ID: <200510132130.j9DLUNga071234@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR bin/45478; it has been noted by GNATS. From: Nate Eldredge <nge@cs.hmc.edu> To: bug-followup@FreeBSD.org, olli@secnetix.de Cc: keramida@freebsd.org Subject: Re: bin/45478: /bin/sh coredump Date: Thu, 13 Oct 2005 14:24:07 -0700 (PDT) I have reproduced this and have a fix. It does seem to have been INTON/INTOFF. To find where the signal was being handled inside malloc, in gdb you can do handle SIGINT nostop pass (answer yes) break exraise command where continue end run which will print a stack trace every time it handles the signal. Then you look for malloc inside the trace. I found the following offenders: #11 0x0805bba7 in redirect (redir=0x0, flags=1) at redir.c:111 #11 0x0805e1a3 in setvar (name=0x80dd76e "_", val=0x810d0ac "true", flags=0) at var.c:246 However, a casual glance revealed several other un-wrapped calls. 90% of these are made via ckmalloc/ckrealloc/ckfree. Thus I think the easiest and safest thing to do is to call INTON/INTOFF inside these functions. They are safe to use recursively and have trivial overhead (incrementing a counter). Here is a patch which does this. It is against CURRENT but I imagine it will apply to other versions as well. After this patch I cannot make it crash anymore. I found only one unsafe use of malloc/free directly: in the umask builtin. umaskcmd() calls setmode() which calls malloc, and then calls free. My patch puts INTON/INTOFF around this as well. By the way, I think the CPU usage thing is a red herring. I assume the numbers are from top, and its CPU field is an average. It definitely decays slowly to 0 after a process has been running, so it can report nonzero even for a totally idle process. sh gets commands from the user with a blocking read, so it must be idle while waiting for input. diff -ur /usr/src/bin/sh/memalloc.c ./src/bin/sh/memalloc.c --- /usr/src/bin/sh/memalloc.c Tue Apr 6 13:06:51 2004 +++ ./src/bin/sh/memalloc.c Thu Oct 13 14:02:30 2005 @@ -57,8 +57,10 @@ { pointer p; + INTOFF; if ((p = malloc(nbytes)) == NULL) error("Out of space"); + INTON; return p; } @@ -70,11 +72,20 @@ pointer ckrealloc(pointer p, int nbytes) { + INTOFF; if ((p = realloc(p, nbytes)) == NULL) error("Out of space"); + INTON; return p; } +void +ckfree(pointer p) +{ + INTOFF; + free(p); + INTON; +} /* * Make a copy of a string in safe storage. diff -ur /usr/src/bin/sh/memalloc.h ./src/bin/sh/memalloc.h --- /usr/src/bin/sh/memalloc.h Tue Apr 6 13:06:51 2004 +++ ./src/bin/sh/memalloc.h Thu Oct 13 14:01:27 2005 @@ -48,6 +48,7 @@ pointer ckmalloc(int); pointer ckrealloc(pointer, int); +void ckfree(pointer); char *savestr(char *); pointer stalloc(int); void stunalloc(pointer); @@ -72,5 +73,3 @@ #define STTOPC(p) p[-1] #define STADJUST(amount, p) (p += (amount), sstrnleft -= (amount)) #define grabstackstr(p) stalloc(stackblocksize() - sstrnleft) - -#define ckfree(p) free((pointer)(p)) diff -ur /usr/src/bin/sh/miscbltin.c ./src/bin/sh/miscbltin.c --- /usr/src/bin/sh/miscbltin.c Fri Sep 9 12:59:41 2005 +++ ./src/bin/sh/miscbltin.c Thu Oct 13 14:00:13 2005 @@ -274,12 +274,14 @@ umask(mask); } else { void *set; + INTOFF; if ((set = setmode (ap)) == 0) error("Illegal number: %s", ap); mask = getmode (set, ~mask & 0777); umask(~mask & 0777); free(set); + INTON; } } return 0; -- Nate Eldredge nge@cs.hmc.edu
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200510132130.j9DLUNga071234>