Bug 624438 (CVE-2010-2941) - CVE-2010-2941 cups: cupsd memory corruption vulnerability
Summary: CVE-2010-2941 cups: cupsd memory corruption vulnerability
Keywords:
Status: CLOSED ERRATA
Alias: CVE-2010-2941
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
high
high
Target Milestone: ---
Assignee: Red Hat Product Security
QA Contact:
URL:
Whiteboard:
Depends On: 646767 646768 646769 646770 652161
Blocks:
TreeView+ depends on / blocked
 
Reported: 2010-08-16 13:21 UTC by Tomas Hoger
Modified: 2023-05-11 15:53 UTC (History)
5 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2011-01-07 12:46:48 UTC
Embargoed:


Attachments (Terms of Use)
cups-value-tag-mismatch.patch (2.13 KB, patch)
2010-08-16 14:21 UTC, Tim Waugh
no flags Details | Diff
cups-CVE-2010-2941-EL5.patch (1.84 KB, patch)
2010-08-31 15:36 UTC, Tim Waugh
no flags Details | Diff
Alternate fix from Mike Sweet, upstream CUPS author and maintainer (2.27 KB, patch)
2010-08-31 19:44 UTC, Tomas Hoger
no flags Details | Diff
Mike's patch back-ported to RHEL5 (1.88 KB, patch)
2010-09-01 10:06 UTC, Tim Waugh
no flags Details | Diff


Links
System ID Private Priority Status Summary Last Updated
CUPS Bugs and Features 3648 0 None None None Never
Red Hat Product Errata RHSA-2010:0811 0 normal SHIPPED_LIVE Important: cups security update 2010-10-29 01:44:07 UTC
Red Hat Product Errata RHSA-2010:0866 0 normal SHIPPED_LIVE Important: cups security update 2010-11-09 19:00:34 UTC

Description Tomas Hoger 2010-08-16 13:21:56 UTC
Emmanuel Bouillon reported a memory corruption flaw in CUPS daemon.  A specially-crafted IPP request can cause daemon to crash or, possibly, execute arbitrary code.

Acknowledgements:

Red Hat would like to thank Emmanuel Bouillon of NATO C3 Agency for reporting this issue.

Comment 1 Tim Waugh 2010-08-16 14:20:11 UTC
The problem is a mismatch between different memory allocators.

In the IPP protocol, an attribute can have multiple values, and each value is typed.  In the CUPS data model for this, all values for a given attribute must have the same (or a compatible) type.

String types have values allocated with the StrAlloc allocator, a reference-counting string pool.

'Unknown' types use malloc.

By giving the first value for an attribute a value tag of 56, which does not correspond to any particular value type and so is 'unknown', but which also is accepted as 'compatible' with string types due to the value tag range check, CUPS does not reject the request.  The 'unknown' value is allocated using malloc; the remaining values are allocated using StrAlloc.

When the in-memory request is freed, free() is used for all values including those allocated using StrAlloc.

The solution is to use exactly the same conditions when deciding how to allocate the value as when freeing it.

The initial value is allocated using malloc(), as it does not match any of the value tag cases.  Successive values are allocated using StrAlloc because they are string types.

Here is the compatibility check just before the successive values are allocated (cups/ipp.c); here, value_tag is the value tag given to the first value, and tag is the value tag given to the current (successive) value:

           /*
            * Make sure we aren't adding a new value of a different
            * type...
            */

            if (value_tag == IPP_TAG_ZERO)
            {
             /*
              * Setting the value of a collection member...
              */

              attr->value_tag = tag;
            }
            else if ((value_tag >= IPP_TAG_TEXTLANG &&
                      value_tag <= IPP_TAG_MIMETYPE))
            {
             /*
              * String values can sometimes come across in different
              * forms; accept sets of differing values...
              */
             /*
              * String values can sometimes come across in different
              * forms; accept sets of differing values...
              */

              if ((tag < IPP_TAG_TEXTLANG || tag > IPP_TAG_MIMETYPE) &&
                  tag != IPP_TAG_NOVALUE)
              {
                DEBUG_printf(("1ippReadIO: 1setOf value tag %x(%s) != %x(%s)",
                              value_tag, ippTagString(value_tag), tag,
                              ippTagString(tag)));
                ipp_buffer_release(buffer);
                return (IPP_ERROR);
              }
            }
            else if (value_tag != tag)
            {
              DEBUG_printf(("1ippReadIO: value tag %x(%s) != %x(%s)",
                            value_tag, ippTagString(value_tag), tag,
                            ippTagString(tag)));
              ipp_buffer_release(buffer);
              return (IPP_ERROR);
            }

Now, IPP_TAG_TEXTLANG < 56 < IPP_TAG_MIMETYPE, so '56' is allowed to be compatible with string types -- even though it uses a different allocator.

Here is how the data is freed:

    default :
        if (!((int)attr->value_tag & IPP_TAG_COPY))
        {
          for (i = 0, value = attr->values;
               i < attr->num_values;
               i ++, value ++)
            if (value->unknown.data)
              free(value->unknown.data);
        }
        break;

(because all the values are collected together under the '56' value tag).

As far as I have been able to tell from source code inspection, all versions of CUPS are vulnerable to this denial of service attack.

Comment 2 Tim Waugh 2010-08-16 14:21:18 UTC
Created attachment 438968 [details]
cups-value-tag-mismatch.patch

Patch attached (for RHEL-6) to fix the compatibility check to use exactly the same checking as in _ippAttrFree().

Comment 3 Tim Waugh 2010-08-16 15:43:30 UTC
RHEL-3 and RHEL-4 are not vulnerable to this because they do not use the string pool/StrAlloc allocator, only malloc (in fact strdup).

Comment 5 Tomas Hoger 2010-08-17 09:33:51 UTC
(In reply to comment #1)
> As far as I have been able to tell from source code inspection, all versions
> of CUPS are vulnerable to this denial of service attack.

There are differences in the impact between 1.3 and 1.4 CUPS versions due to the differences in the way _cups_sp_item_t is organized.

In 1.4, _cups_sp_item_t is:

     71 typedef struct _cups_sp_item_s		/**** String Pool Item ****/
     72 {
     73 #  ifdef DEBUG_GUARDS
     74   unsigned int	guard;			/* Guard word */
     75 #  endif /* DEBUG_GUARDS */
     76   unsigned int	ref_count;		/* Reference count */
     77   char		str[1];			/* String */
     78 } _cups_sp_item_t;

_cupsStrAlloc() allocates new item as:
  calloc(1, sizeof(_cups_sp_item_t) + strlen(s))

and returns str pointer.  Therefore, _cupsStrFree() calls free() on a value point to the middle of the malloced chunk, triggering glibc malloc checks failure and abort.

In 1.3, _cups_sp_item_t is:

     69 typedef struct _cups_sp_item_s		/**** String Pool Item ****/
     70 {
     71   char		*str;			/* String */
     72   unsigned int	ref_count;		/* Reference count */
     73 } _cups_sp_item_t;

and str is strdup()-allocated independently of the structure.  Hence value passed to free() from _cupsStrFree() points to valid malloc()ed chunk that can be freed, but string pool item is not properly ref-counted and removed from string pool, that may lead to use-after-free with possible additional memory corruptions.

Comment 8 Tomas Hoger 2010-08-25 13:08:14 UTC
Status update: we still don't have any embargo date proposal from Apple security team.  No changes in the upstream bug.

Comment 9 Tim Waugh 2010-08-31 15:36:03 UTC
Created attachment 442221 [details]
cups-CVE-2010-2941-EL5.patch

Same patch back-ported to Red Hat Enterprise Linux 5.

Comment 10 Tomas Hoger 2010-08-31 19:44:52 UTC
Created attachment 442263 [details]
Alternate fix from Mike Sweet, upstream CUPS author and maintainer

Comment 11 Tim Waugh 2010-09-01 10:06:33 UTC
Created attachment 442372 [details]
Mike's patch back-ported to RHEL5

Comment 12 Tomas Hoger 2010-09-03 08:45:17 UTC
Update from Apple Product Security:

We're currently planning on including this fix in our next Mac OS X update.  At this time, we don't have a date for when the fix might be available.

Comment 13 manu 2010-09-23 14:19:31 UTC
6 weeks now. Any news regarding the disclosure date?

Comment 14 Tomas Hoger 2010-09-23 14:34:30 UTC
No update from Apple on disclosure date so far.

Comment 15 Tomas Hoger 2010-10-05 07:43:02 UTC
New upstream release is expected in about 1 month, based on what we've been told.

Comment 18 Tomas Hoger 2010-10-26 07:41:27 UTC
Apple is planning to release late this week.

Comment 20 Vincent Danen 2010-10-29 01:29:18 UTC
The new upstream release is not available yet, but we have been given the go-ahead to observe the original embargo (today) and release.

Comment 22 errata-xmlrpc 2010-10-29 01:44:12 UTC
This issue has been addressed in following products:

  Red Hat Enterprise Linux 5

Via RHSA-2010:0811 https://rhn.redhat.com/errata/RHSA-2010-0811.html

Comment 23 errata-xmlrpc 2010-11-10 18:57:55 UTC
This issue has been addressed in following products:

  Red Hat Enterprise Linux 6

Via RHSA-2010:0866 https://rhn.redhat.com/errata/RHSA-2010-0866.html

Comment 24 Tomas Hoger 2010-11-11 08:15:21 UTC
Created cups tracking bugs for this issue

Affects: fedora-all [bug 652161]


Note You need to log in before you can comment on or make changes to this bug.