ports/81372: gpasm is vulnerable to a buffer overflow

Shaun Colley scolleyuk at gmail.com
Sun May 22 21:10:02 UTC 2005


>Number:         81372
>Category:       ports
>Synopsis:       gpasm is vulnerable to a buffer overflow
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun May 22 21:10:02 GMT 2005
>Closed-Date:
>Last-Modified:
>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:
>Unformatted:



More information about the freebsd-ports-bugs mailing list