Bug 8000 - [type1] integer overflow in scan_cidfont()
[type1] integer overflow in scan_cidfont()
Status: RESOLVED FIXED
Product: xorg
Classification: Unclassified
Component: Server/General
git
x86 (IA32) Linux (All)
: high normal
Assigned To: X.Org Security
: security
: 8006 8028 (view as bug list)
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2006-08-25 08:48 UTC by Daniel Stone
Modified: 2006-09-13 15:48 UTC (History)
4 users (show)

See Also:


Attachments
proposed patch for both issues (2.17 KB, patch)
2006-08-28 14:18 UTC, Matthieu Herrb
no flags Details | Splinter Review
libXfont.diff (2.18 KB, patch)
2006-09-05 12:56 UTC, Stefan Dirsch
no flags Details | Splinter Review

Note You need to log in before you can comment on or make changes to this bug.
Description Daniel Stone 2006-08-25 08:48:50 UTC
yay root access woo.  no embargo date set.

quoting iDefense:
--
Local exploitation of an integer overflow vulnerability in the 'scan_cidfont()'
function in the X.Org and XFree86 X server could allow an attacker to execute
arbitrary code with privileges of the X server, typically root.

The vulnerability specifically exists in the handling of 'CMap' and 'CIDFont'
font data. When parsing this information no checks are made that the count of
items for the 'begincodespacerange', 'cidrange' and 'notdefrange' sections. The
following section of code shows where the vulnerability is:

=== X.Org/xc/lib/font/Type1/scanfont.c ===

     1621  int
     1622  scan_cidfont(cidfont *CIDFontP, cmapres *CMapP)
     1623  {
      ...
     1704    if (!(fileP1 = fopen(cmapfile,filetype)))
     1705      return(SCAN_FILE_OPEN_ERROR);
     1706
     1707    objFormatFile(inputP,fileP1);
      ...
     1716    do {
     1717      /* Scan the next token */
     1718      scan_token(inputP);
     1719      if (tokenType == TOKEN_INTEGER)
[1]  1720        rangecnt = tokenValue.integer;
      ...
     1725      switch (tokenType) {
      ...
     1742        case TOKEN_NAME:
     1743          if (0 == strncmp(tokenStartP,"begincodespacerange",19)) {
      ...
     1752            spacerangeP->spacecode =
[2]  1753              (spacerangecode *)vm_alloc(rangecnt*sizeof(spacerangecode));
     1754            if (!spacerangeP->spacecode) {
     1755              rc = SCAN_OUT_OF_MEMORY;
     1756              break;
     1757            }
[3]  1758            for (i = 0; i < rangecnt; i++) {
     1759              scan_token(inputP);
[4]  1760              if (tokenType != TOKEN_HEX_STRING) {
     1761                rc = SCAN_ERROR;
     1762                break;
     1763              }
      ...

At [1] the count of array items 'rangecnt' is loaded. This can have any integer
value, including negative numbers. Then, at [2], the memory for the array data
is allocated. If 'rangecnt' is chosen such that when it is multiplied by the
size of the structure it is too big to completely fit in an integer, less memory
than is requested will be allocated. The program then attempts [3] to read in
'rangecnt' elements, but will stop reading values in if there is an error in the
input. This error checking means a controlled amount of data can be used to
overwrite the heap.

In addition to a 'standard' integer overflow, the implementation of 'vm_alloc()'
makes it possible to overwrite memory before the allocated region.

=== X.Org/xc/lib/font/Type1/util.c ===

       98  char *
       99  vm_alloc(int bytes)
      100  {
      101    char *answer;
      102
      103    /* Round to next word multiple */
      104    bytes = (bytes + 7) & ~7;
      105
      106    /* Allocate the space, if it is available */
[1]   107    if (bytes <= vm_free) {
[2]   108      answer = vm_next;
[3]   109      vm_free -= bytes;
[4]   110      vm_next += bytes;
      111    }
      112    else
      113      answer = NULL;
      114
      115    return(answer);
      116  }

If this function is called with a negative value for 'bytes', the check at [1]
passes, the response is set to the current end of the allocated pool at [2], the
amount of free space available is increased at [3] and the pointer to use next
time is moved backwards at [4] into already used memory.
--
Comment 1 Matthieu Herrb 2006-08-28 14:17:17 UTC
*** Bug 8028 has been marked as a duplicate of this bug. ***
Comment 2 Alan Coopersmith 2006-08-28 14:17:51 UTC
*** Bug 8006 has been marked as a duplicate of this bug. ***
Comment 3 Matthieu Herrb 2006-08-28 14:18:10 UTC
Created attachment 6731 [details] [review]
proposed patch for both issues
Comment 4 Matthieu Herrb 2006-09-01 02:46:08 UTC
This is CVE-2006-3740
Comment 5 Stefan Dirsch 2006-09-05 12:56:31 UTC
Created attachment 6830 [details] [review]
libXfont.diff

Patch in attachment #6731 [details] [review] results in a compile failure in module subdir, since
INT_MAX/LONG_MAX is already defined in xf86_libc.h, but this one builds fine.
Comment 6 Alan Coopersmith 2006-09-13 15:48:01 UTC
Patches committed and advisory released.