From nobody@FreeBSD.org  Sun May 22 21:02:17 2005
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id AFAC316A41C
	for <freebsd-gnats-submit@FreeBSD.org>; Sun, 22 May 2005 21:02:17 +0000 (GMT)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [216.136.204.117])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 8189643D5C
	for <freebsd-gnats-submit@FreeBSD.org>; Sun, 22 May 2005 21:02:17 +0000 (GMT)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.13.1/8.13.1) with ESMTP id j4ML2HGD082025
	for <freebsd-gnats-submit@FreeBSD.org>; Sun, 22 May 2005 21:02:17 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.13.1/8.13.1/Submit) id j4ML2H6e082024;
	Sun, 22 May 2005 21:02:17 GMT
	(envelope-from nobody)
Message-Id: <200505222102.j4ML2H6e082024@www.freebsd.org>
Date: Sun, 22 May 2005 21:02:17 GMT
From: Shaun Colley <scolleyuk@gmail.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: gpasm is vulnerable to a buffer overflow
X-Send-Pr-Version: www-2.3

>Number:         81372
>Category:       ports
>Synopsis:       gpasm is vulnerable to a buffer overflow
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    pav
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun May 22 21:10:02 GMT 2005
>Closed-Date:    Thu Jun 30 10:57:59 GMT 2005
>Last-Modified:  Thu Jun 30 10:57:59 GMT 2005
>Originator:     Shaun Colley
>Release:        FreeBSD 5.3-RELEASE
>Organization:
>Environment:
bash-3.00# uname -a
FreeBSD my.host.name 5.3-RELEASE FreeBSD 5.3-RELEASE #6: Thu Mar 10 21:08:45 GMT 2005     my.host.name:/usr/src/sys/i386/compile/GENERIC  i386
>Description:
gpasm, part of the devel/gputils port, is vulnerable to a stack overflow when parsing assembly code.  gpasm will segmentation fault when given a long directive in a source file.  If a user were tricked into assembling a source file, attacker-controlled code could be executed, giving rise to a security risk.

I *suspect* that the problem exists in gp_cod_strncpy, 'libgputils' strncpy wrapper.  gp_cod_strncpy's code is as follows:

---
/* copy a string to a cod block using the pascal convention, i.e. the
   string length occupies the first string location */

void
gp_cod_strncpy(char *dest, char *src, int max_len)
{

  *(dest-1) = ( (max_len>strlen(src)) ? strlen(src) : max_len );
  strncpy(dest, src, *(dest-1));

}
---

Although the routine's use of strncpy() may make it look secure, it may not be, because it uses the length of the source as the maximum length.

I can not be *absolutely* sure where the overflow is caused, but the above is my suspicion.
>How-To-Repeat:
Simply feed gpasm a malformed file with a long 'directive'.  Here's my test file:

---
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
END
---

Upon being fed to gpasm, a seg fault should occur:

---
bash-3.00# ./gpasm a
Warning [226] Must use inhx8m format for EEPROM8
Segmentation fault (core dumped)
bash-3.00#
---

It seems evident that a stack overflow *is* actually occuring by observing execution in GDB.

---
bash-3.00# ./gpasm a
Warning [226] Must use inhx8m format for EEPROM8
Segmentation fault (core dumped)
bash-3.00# gdb -q -c gpasm.core
Core was generated by `gpasm'.
Program terminated with signal 11, Segmentation fault.
#0  0x2812bbb4 in ?? ()
(gdb) bt
#0  0x2812bbb4 in ?? ()
#1  0x0809c200 in ?? ()
#2  0xbfbfe788 in ?? ()
#33 0x00000001 in ?? ()
#34 0x00000004 in ?? ()

[...]

#37 0x61616161 in ?? ()
#38 0x61616161 in ?? ()
#39 0x61616161 in ?? ()
#40 0x61616161 in ?? ()
#41 0x61616161 in ?? ()
#42 0x61616161 in ?? ()
#43 0x61616161 in ?? ()
#44 0x61616161 in ?? ()
#45 0x61616161 in ?? ()
---Type <return> to continue, or q <return> to quit---Q

[...]

---

And here's another log:

---
bash-3.00# gdb -q ./gpasm
(no debugging symbols found)...(gdb) run a
Starting program: /usr/ports/devel/gputils/work/gputils-0.12.0/gpasm/gpasm a
(no debugging symbols found)...(no debugging symbols found)...Warning [226] Must use inhx8m format for EEPROM8

Program received signal SIGSEGV, Segmentation fault.
0x2812bbb4 in strncpy () from /lib/libc.so.5
(gdb) 

[...]

(gdb) bt full
#0  0x2812bbb4 in strncpy () from /lib/libc.so.5
No symbol table info available.
#1  0x08057989 in gp_cod_strncpy ()
No symbol table info available.
#2  0x08050a52 in cod_write_symbols ()
No symbol table info available.
#3  0x0804da77 in lst_symbol_table ()
No symbol table info available.
#4  0x080499a4 in assemble ()
No symbol table info available.
#5  0x080490cc in main ()
No symbol table info available.
---

Though I could be wrong on the whole thing together, this seems like a stack overflow, triggered by a malformed source file, due to lack of proper bounds checking in gp_cod_strncpy().

I'm not sure how exploitable this would be, since there seem to be quite a few frames that need to be popped before the overwritten return address finally gets jumped to - and by the looks of it, gpasm seg faults before that, else the return address upon crash would probably be 0x61616161.

I haven't look at how exploitable it might be yet - any thoughts on that?
>Fix:
Further proof that a call to gp_cod_strncpy() is the culprit is the fact that this patch fixes it:

--- gpcod.orig.c        Sun May 22 21:55:08 2005
+++ gpcod.c     Sun May 22 21:55:30 2005
@@ -29,8 +29,8 @@
 gp_cod_strncpy(char *dest, char *src, int max_len)
 {

-  *(dest-1) = ( (max_len>strlen(src)) ? strlen(src) : max_len );
-  strncpy(dest, src, *(dest-1));
+  /**(dest-1) = ( (max_len>strlen(src)) ? strlen(src) : max_len )*/;
+  strncpy(dest, src, 80);

 }

If the patch is applied to /usr/ports/devel/gputils/work/gputils-0.12.0/libgputils/gpcod.c, the overflow no longer exists:

---
bash-3.00# ./gpasm a
Warning [226] Must use inhx8m format for EEPROM8
bash-3.00#
---

I haven't given my opinion on which call to gp_cod_strncpy() is responsible, because fixing the actual wrapper function is probably a more reliable way.

The above patch is rough.  I have no idea as to the actual requirements of string lengths - 80 might be too short, or too long.

I'm sorry if this was too brief, or too many copy-and-pastes were done.  I did this in a hurry because I've got revision to be doing. :)


>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->feedback 
State-Changed-By: pav 
State-Changed-When: Sun Jun 5 20:54:00 GMT 2005 
State-Changed-Why:  
Where does this leave us as Ports collection keepers? This all feels like 
something you should take up with authors of the software. 

Anyway, the port is outdated, website have 0.13.2 release... time to contact 
maintainer to update the port, or to submit update yourself in case maintainer 
is unresponsive? 


Responsible-Changed-From-To: freebsd-ports-bugs->pav 
Responsible-Changed-By: pav 
Responsible-Changed-When: Sun Jun 5 20:54:00 GMT 2005 
Responsible-Changed-Why:  
Track 

http://www.freebsd.org/cgi/query-pr.cgi?pr=81372 
State-Changed-From-To: feedback->closed 
State-Changed-By: pav 
State-Changed-When: Thu Jun 30 10:57:48 GMT 2005 
State-Changed-Why:  
Feedback timeout 

http://www.freebsd.org/cgi/query-pr.cgi?pr=81372 
>Unformatted:
