Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 25 Apr 2005 23:32:16 GMT
From:      "Wojciech A. Koszek" <dunstan@freebsd.czest.pl>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   bin/80346: [PATCH] Misuse of el_init() can lead multiple programs to SIGSEGV
Message-ID:  <200504252332.j3PNWGLG003380@freebsd.czest.pl>
Resent-Message-ID: <200504252330.j3PNUGg4052630@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         80346
>Category:       bin
>Synopsis:       [PATCH] Misuse of el_init() can lead multiple programs to SIGSEGV
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Apr 25 23:30:15 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     Wojciech A. Koszek
>Release:        FreeBSD 5.3-RELEASE-p5 i386
>Organization:
>Environment:
System: FreeBSD dunstan.freebsd.czest.pl 5.3-RELEASE-p5 FreeBSD 5.3-RELEASE-p5 #4: Sun Mar 6 10:50:43 CET 2005 dunstan@ho:/usr/obj/usr/src/sys/HOME7 i386


>Description:
There is a problem in multiple programs which make use of editline library
which may lead software to crash.
Code placed in sys/kern/tty.c makes it possible to set TTY size to arbitrary
values. Number of rows and columns is kept in unsigned short variables.
Setting the biggest values for those variables is possible with stty(1):

	$ stty rows -1
	$ stty columns -1

After running applications with changed terminal size, further allocations
are done on given (very big) size. Allocation may not succeed and
applications which don't check return value of el_init() continue executing,
and thus, get SIGSEGV. This problem may have security implications --
programs linked with editline run with raised privileges (lpc). Known
problems:
src/usr.sbin/lpr/lpc/lpc.c
[..]
	if (!el) {
 		el = el_init("lpc", stdin, stdout, stderr);
		hist = history_init();
		history(hist, &he, H_EVENT, 100);
		el_set(el, EL_HIST, history, hist);					
[..]

src/usr.bin/tftp/main.c:
[..]
	vrbose = isatty(0);
	if (vrbose) {
       		el = el_init("tftp", stdin, stdout, stderr);
		hist = history_init();
	}
[..]

src/usr.sbin/cdcontrol/cdcontrol.c
[..]
	if (!el) {
		el = el_init("cdcontrol", stdin, stdout, stderr);
		hist = history_init();
		history(hist, &he, H_EVENT, 100);
[..]

src/usr.sbin/pppctl/pppctl.c
[..]
                history(td.hist, &hev, H_SETSIZE, size);
                td.edit = el_init("pppctl", stdin, stdout, stderr);
[..]

..and probably more.
>How-To-Repeat:
Preparation:

dunstan@dunstan:(~)$ stty rows -1
dunstan@dunstan:(~)$ stty columns -1
dunstan@dunstan:(~)$ stty -a | head -1
speed 38400 baud; 65535 rows; 65535 columns;

dunstan@dunstan:(~)$ lpc
zsh: segmentation fault  lpc

>Fix:
*Library* fix
el_init() should check result of term_init() and return NULL if term_init()
returned -1. Every application has to be corrected separately to properly
handle return value of el_init().

--- diff.0.el.c begins here ---
--- /usr/src/lib/libedit/el.c	Tue Apr 26 00:51:51 2005
+++ src/lib/libedit/el.c	Tue Apr 26 01:01:20 2005
@@ -74,14 +74,21 @@ el_init(const char *prog, FILE *fin, FIL
 	el->el_infd = fileno(fin);
 	el->el_outfile = fout;
 	el->el_errfile = ferr;
-	el->el_prog = strdup(prog);
+	if ((el->el_prog = strdup(prog)) == NULL) {
+		el_free(el);
+		return (NULL);
+	}
 
 	/*
          * Initialize all the modules. Order is important!!!
          */
 	el->el_flags = 0;
 
-	(void) term_init(el);
+	if (term_init(el) == -1) {
+		free(el->el_prog);
+		el_free(el);
+		return (NULL);
+	}
 	(void) key_init(el);
 	(void) map_init(el);
 	if (tty_init(el) == -1)
--- diff.0.el.c ends here ---

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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200504252332.j3PNWGLG003380>