Date: Sun, 12 May 2002 16:17:44 -0700 (PDT) From: Marcel Moolenaar <marcel@xcllnt.net> To: freebsd-gnats-submit@FreeBSD.org Subject: bin/38006: tcsh calls malloc() from signal handler without serialization Message-ID: <200205122317.g4CNHiKH067491@www.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 38006 >Category: bin >Synopsis: tcsh calls malloc() from signal handler without serialization >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Sun May 12 16:20:01 PDT 2002 >Closed-Date: >Last-Modified: >Originator: Marcel Moolenaar >Release: none :-) >Organization: >Environment: FreeBSD dhcp01.pn.xcllnt.net 5.0-CURRENT FreeBSD 5.0-CURRENT #0: Sat May 4 15:29:52 PDT 2002 marcel@dhcp01.pn.xcllnt.net:/usr/obj/usr/src/sys/VAIO i386 >Description: At startup, for example when opening a GNOME terminal with tcsh as the users shell, there's a possibility that a SIGWINCH is delivered while tcsh is in free(). A SIGWINCH signal causes the display buffer to be recreated (ReBufferDisplay()) and will call result in calls to free() and malloc(). The following stacktrace demonstrates what happens: (gdb) bt #0 0x808e4a3 in access () #1 0x80ba9fa in abort () at /usr/src/lib/libc/../libc/stdlib/abort.c:78 #2 0x80b97a9 in wrtwarning (p=0x80ef54e "in free():") at /usr/src/lib/libc/../libc/stdlib/malloc.c:314 #3 0x80b97c8 in wrtwarning (p=0x80ef54e "in free():") at /usr/src/lib/libc/../libc/stdlib/malloc.c:315 #4 0x80ba5aa in malloc (size=1644) at /usr/src/lib/libc/../libc/stdlib/malloc.c:1093 #5 0x8079163 in smalloc (n=1644) at /usr/src/bin/csh/../../contrib/tcsh/tc.alloc.c:505 #6 0x80757d8 in ReBufferDisplay () at /usr/src/bin/csh/../../contrib/tcsh/ed.screen.c:506 #7 0x8077cf9 in ChangeSize (lins=24, cols=80) at /usr/src/bin/csh/../../contrib/tcsh/ed.screen.c:1742 #8 0x8071542 in check_window_size (force=0) at /usr/src/bin/csh/../../contrib/tcsh/ed.init.c:128 #9 0x8071564 in window_change (snum=28) at /usr/src/bin/csh/../../contrib/tcsh/ed.init.c:148 #10 <signal handler called> #11 0x80baa8f in memcpy () #12 0x80ba6c9 in free (ptr=0x814f600) at /usr/src/lib/libc/../libc/stdlib/malloc.c:1125 #13 0x8079287 in sfree (p=0x814f600) at /usr/src/bin/csh/../../contrib/tcsh/tc.alloc.c:586 #14 0x805c2ca in blkfree (av0=0x814f600) at /usr/src/bin/csh/../../contrib/tcsh/sh.misc.c:169 #15 0x8057600 in backeval (cp=0x8150900, literal=0) at /usr/src/bin/csh/../../contrib/tcsh/sh.glob.c:842 #16 0x80574e8 in dobackp (cp=0x8147060, literal=0) at /usr/src/bin/csh/../../contrib/tcsh/sh.glob.c:784 #17 0x8056aa1 in globexpand (v=0x814ac54) at /usr/src/bin/csh/../../contrib/tcsh/sh.glob.c:386 #18 0x8057171 in globall (v=0x814ac50) at /usr/src/bin/csh/../../contrib/tcsh/sh.glob.c:632 #19 0x80622c1 in set1 (var=0x814acf0, vec=0x814ac50, head=0x8130fc4, flags=2) at /usr/src/bin/csh/../../contrib/tcsh/sh.set.c:616 #20 0x806227a in set (var=0x814acf0, val=0x8147060, flags=2) at /usr/src/bin/csh/../../contrib/tcsh/sh.set.c:601 #21 0x8061a41 in doset (v=0x814f200, c=0x814cce0) at /usr/src/bin/csh/../../contrib/tcsh/sh.set.c:292 #22 0x8053428 in func (t=0x814cce0, bp=0x80f4a44) at /usr/src/bin/csh/../../contrib/tcsh/sh.func.c:149 #23 0x80608d7 in execute (t=0x814cce0, wanttty=634, pipein=0x0, pipeout=0x0) at /usr/src/bin/csh/../../contrib/tcsh/sh.sem.c:657 #24 0x8060b15 in execute (t=0x814ccc0, wanttty=634, pipein=0x0, pipeout=0x0) at /usr/src/bin/csh/../../contrib/tcsh/sh.sem.c:734 #25 0x804a847 in process (catch=0) at /usr/src/bin/csh/../../contrib/tcsh/sh.c:2125 #26 0x804a0f9 in srcunit (unit=3, onlyown=1, hflg=0, av=0x0) at /usr/src/bin/csh/../../contrib/tcsh/sh.c:1661 #27 0x8049cce in srcfile (f=0x814b700 "USER", onlyown=1, flag=0, av=0x0) at /usr/src/bin/csh/../../contrib/tcsh/sh.c:1468 #28 0x8049c70 in srccat (cp=0x814ca00, dp=0x80f64a4) at /usr/src/bin/csh/../../contrib/tcsh/sh.c:1441 #29 0x8049973 in main (argc=0, argv=0xbfbffaa4) at /usr/src/bin/csh/../../contrib/tcsh/sh.c:1301 malloc() and free() are not reentrant and thus should be protected from this situation. >How-To-Repeat: One approach would be to hack free() in libc to do a kill(getpid(), SIGWINCH). The following patch has been verified to simulate the condition (probably white-space corrupted): Index: malloc.c =================================================================== RCS file: /home/ncvs/src/lib/libc/stdlib/malloc.c,v retrieving revision 1.68 diff -u -r1.68 malloc.c --- malloc.c 24 Apr 2002 16:49:36 -0000 1.68 +++ malloc.c 12 May 2002 23:12:35 -0000 @@ -1120,8 +1120,10 @@ THREAD_UNLOCK(); return; } - if (ptr != ZEROSIZEPTR) - ifree(ptr); + if (ptr != ZEROSIZEPTR) { + kill(getpid(), 28); + ifree(ptr); + } UTRACE(ptr, 0, 0); malloc_active--; THREAD_UNLOCK(); >Fix: Suggested fixes: o Don't malloc from a signal handler, o Block SIGWINCH in sfree(). >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200205122317.g4CNHiKH067491>