Subject: lib/2780: potential security hole in __strerror() & __strsignal()
To: None <gnats-bugs@gnats.netbsd.org>
From: Mike Long <mike.long@analog.com>
List: netbsd-bugs
Date: 09/25/1996 03:32:20
>Number:         2780
>Category:       lib
>Synopsis:       potential security hole in __strerror() & __strsignal()
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    lib-bug-people (Library Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Sep 25 00:50:00 1996
>Last-Modified:
>Originator:     Mike Long <mike.long@analog.com>
>Organization:
	
>Release:        1.2_BETA
>Environment:
	
System: NetBSD azathoth 1.2_BETA NetBSD 1.2_BETA (AZATHOTH) #100: Mon Sep 2 21:56:30 EDT 1996 root@azathoth:/usr/src/sys/arch/i386/compile/AZATHOTH i386


>Description:
	__strerror() and __strsignal() use sprintf() and strcpy()
instead of the more-robust snprintf() and strncpy().  If I'm
interpreting the code correctly, rogue users can corrupt the stack in
any program that uses strerror(), &c., by feeding the NLS system a bad
message catalog.

>How-To-Repeat:
	fgrep -l _sprintf /usr/obj/lib/libc/*.o
	fgrep -l _strcpy /usr/obj/lib/libc/*.o
>Fix:
	Apply the patches below.  I assume that since __strerror() and
__strsignal() are private functions, they can make assumptions about
the buffer length.

*** /usr/src/lib/libc/string/__strerror.c~	Sat Jan 20 07:15:57 1996
--- /usr/src/lib/libc/string/__strerror.c	Wed Sep 25 02:45:45 1996
***************
*** 48,51 ****
--- 48,52 ----
  
  #include <errno.h>
+ #include <limits.h>
  #include <stdio.h>
  #include <string.h>
***************
*** 73,78 ****
  	if (errnum < sys_nerr) {
  #ifdef NLS
! 		strcpy(buf, catgets(catd, 1, errnum,
! 		    (char *)sys_errlist[errnum])); 
  #else
  		return(sys_errlist[errnum]);
--- 74,80 ----
  	if (errnum < sys_nerr) {
  #ifdef NLS
! 		strncpy(buf, catgets(catd, 1, errnum,
! 		    (char *)sys_errlist[errnum]), NL_TEXTMAX);
! 		buf[NL_TEXTMAX - 1] = '\0';
  #else
  		return(sys_errlist[errnum]);
***************
*** 80,86 ****
  	} else {
  #ifdef NLS
! 		sprintf(buf, catgets(catd, 1, 0xffff, UPREFIX), errnum);
  #else
! 		sprintf(buf, UPREFIX, errnum);
  #endif
  	}
--- 82,89 ----
  	} else {
  #ifdef NLS
! 		snprintf(buf, NL_TEXTMAX, catgets(catd, 1, 0xffff, UPREFIX),
! 		    errnum);
  #else
! 		snprintf(buf, NL_TEXTMAX, UPREFIX, errnum);
  #endif
  	}

*** /usr/src/lib/libc/string/__strsignal.c~	Fri Oct 13 20:53:19 1995
--- /usr/src/lib/libc/string/__strsignal.c	Wed Sep 25 02:46:17 1996
***************
*** 46,49 ****
--- 46,50 ----
  #define sys_siglist	_sys_siglist
  
+ #include <limits.h>
  #include <stdio.h>
  #include <signal.h>
***************
*** 66,71 ****
  	if (signum < NSIG) {
  #ifdef NLS
! 		strcpy(buf, catgets(catd, 2, signum,
! 		    (char *)sys_siglist[signum])); 
  #else
  		return((char *)sys_siglist[signum]);
--- 67,73 ----
  	if (signum < NSIG) {
  #ifdef NLS
! 		strncpy(buf, catgets(catd, 2, signum,
! 		    (char *)sys_siglist[signum]), NL_TEXTMAX);
! 		buf[NL_TEXTMAX - 1] = '\0';
  #else
  		return((char *)sys_siglist[signum]);
***************
*** 73,79 ****
  	} else {
  #ifdef NLS
! 		sprintf(buf, catgets(catd, 1, 0xffff, UPREFIX), signum);
  #else
! 		sprintf(buf, UPREFIX, signum);
  #endif
  	}
--- 75,82 ----
  	} else {
  #ifdef NLS
! 		snprintf(buf, NL_TEXTMAX, catgets(catd, 1, 0xffff, UPREFIX),
! 		    signum);
  #else
! 		snprintf(buf, NL_TEXTMAX, UPREFIX, signum);
  #endif
  	}


>Audit-Trail:
>Unformatted: