Subject: lib/12863: "screen -T foo" results in coredump in libc/gen/getcap.c
To: None <gnats-bugs@gnats.netbsd.org>
From: Hubert Feyrer <feyrer@smaug.fh-regensburg.de>
List: netbsd-bugs
Date: 05/08/2001 02:55:10
>Number:         12863
>Category:       lib
>Synopsis:       "screen -T foo" results in coredump in libc/gen/getcap.c
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    hubertf
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon May 07 17:55:01 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     Hubert Feyrer
>Release:        1.5.1_BETA as or 20010508
>Organization:
Hubert Feyrer <hubertf@channel.regensburg.org>
>Environment:
	
System: NetBSD miyu 1.5.1_BETA NetBSD 1.5.1_BETA (MIYU) #4: Mon May  7 01:39:40 MEST 2001     feyrer@miyu:/usr/cvs/src-1.5/sys/arch/i386/compile/MIYU i386


>Description:
	"screen -T foo" dumps core when executed by a normal user and
	screen is setuid.

>How-To-Repeat:
	install screen from pkgsrc, run it: screen -T foo
	See it dump core. 

>Fix:
	I'm not sure if this a problem on libc/libcurses/libtermcap,
	or in screen.

	The codepath in screen here is:

		      do {
		        ...
		      if (e_tgetent(buf, p) == 1) {
		        break;
		      strcpy(p, "vt100");
		    }
		  while (0);            /* Goto free programming... */
		
		  /* check for compatibility problems, displays == 0 after fork */
		  {
		    char xbuf[TERMCAP_BUFSIZE], *xbp = xbuf;
		    if (tgetstr("im", &xbp) && tgetstr("ic", &xbp) && displays)
		    ...

	With -T foo, 'p' is set to "foo" for the e_tgetent() call, which is
	just a wrapper for tgetent(). As we don't know term type "foo",
	e_tgetent() fails, and it will strcpy "vt100" into the terminal
	type 'p', but then exits ("while(0)") instead of trying vt100.
	Leaving aside that this is probably a bug in screen, it continues
	after the failed (e_)tgetent(), and calls tgetstr() next. 

	As some internal buffer (fbuf, in termlib/termcap.c) is not properly
	initialized due to the error, a null pointer is passed in info->info
	to t_getstr(), and as we don't have DIAGASSERT() defined by default,
	this is not detected and it finally blows up in _cgetcap(). 

	Can someone confirm that the behaviour of dumping core in this
	situation is wanted, when a program decides to ignore a return code?
	In that case I'd like to point the screen maintainers to the data
	collected in the PR here.

	A diff against screen 3.9.8 that fixes the problem is:
--- termcap.c.orig      Tue May  8 02:43:24 2001
+++ termcap.c
@@ -773,6 +773,13 @@
       if (e_tgetent(buf, p) == 1)
        break;
       strcpy(p, "vt100");
+#if 1
+      if (e_tgetent(buf, p) == 1) {
+       break;
+      } else {
+       abort(); /* no vt100 ...! */
+      }
+#endif
     }
   while (0);           /* Goto free programming... */



	Final comment:
	This problem was not detected by me but by syke@newhackcity.net.
	I just did the debugging of what's wrong.



	The full call tree of the crash in screen is:

Core was generated by `screen'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /usr/libexec/ld.elf_so...done.
Reading symbols from /usr/lib/libcurses.so.3...done.
Reading symbols from /usr/lib/libutil.so.5...done.
Reading symbols from /usr/lib/libcrypt.so.0...done.
Reading symbols from /usr/lib/libc.so.12...done.
#0  0x480f4e03 in _cgetcap (buf=0x0, cap=0xbfbfb51c "im", type=61)
    at /usr/cvs/src-1.5/lib/libc/gen/getcap.c:172
172                             if (*bp == '\0')
(gdb) bt
#0  0x480f4e03 in _cgetcap (buf=0x0, cap=0xbfbfb51c "im", type=61)
    at /usr/cvs/src-1.5/lib/libc/gen/getcap.c:172
#1  0x480f5f2a in _cgetstr (buf=0x0, cap=0xbfbfb51c "im", str=0xbfbfb4fc)
    at /usr/cvs/src-1.5/lib/libc/gen/getcap.c:906
#2  0x480a58d1 in t_getstr (info=0x808cb20, id=0xbfbfb51c "im",
    area=0xbfbfb568, limit=0x0)
    at /usr/cvs/src-1.5/lib/libcurses/../libterm/termcap.c:364
#3  0x480a59a6 in tgetstr (id=0x8076ce2 "im", area=0xbfbfb568)
    at /usr/cvs/src-1.5/lib/libcurses/../libterm/termcap.c:426
#4  0x8060a04 in MakeTermcap (aflag=0) at termcap.c:782
#5  0x8060091 in InitTermcap (wi=0, he=0) at termcap.c:472
#6  0x804baf2 in main (ac=0, av=0xbfbfd4f8) at screen.c:1164
#7  0x8049fb5 in ___start ()


>Release-Note:
>Audit-Trail:
>Unformatted: