|
|
a9d1fb |
Fix for CVE-2020-10001, which is a bug in the CUPS ippReadIO function when it
|
|
|
a9d1fb |
reads tagged string values (nameWithLanguage and textWithLanguage). The
|
|
|
a9d1fb |
previous code verified that the length of the sub-strings (language identifier
|
|
|
a9d1fb |
and name/text value) did not exceed the size of the allocated buffer (1 byte
|
|
|
a9d1fb |
larger than the maximum IPP value size of 32767 bytes), but did not validate
|
|
|
a9d1fb |
against the length of the actual IPP value.
|
|
|
a9d1fb |
|
|
|
a9d1fb |
The issues introduced by this vulnerability include:
|
|
|
a9d1fb |
|
|
|
a9d1fb |
- Potential information disclosure by copying uninitialized areas of memory into
|
|
|
a9d1fb |
an IPP string value.
|
|
|
a9d1fb |
- Potential Denial of Service by supplying/using invalid string values when
|
|
|
a9d1fb |
strict validation has been disabled by the system administrator.
|
|
|
a9d1fb |
|
|
|
a9d1fb |
This change ensures that:
|
|
|
a9d1fb |
|
|
|
a9d1fb |
1. The language identifier does not extend beyond the end of the IPP value.
|
|
|
a9d1fb |
2. The length of the name/text string is within the IPP value.
|
|
|
a9d1fb |
3. The name/text string is within the IPP value.
|
|
|
a9d1fb |
|
|
|
a9d1fb |
diff --git a/cups/ipp.c b/cups/ipp.c
|
|
|
a9d1fb |
index 3d529346c..adbb26fba 100644
|
|
|
a9d1fb |
--- a/cups/ipp.c
|
|
|
a9d1fb |
+++ b/cups/ipp.c
|
|
|
a9d1fb |
@@ -2866,7 +2866,8 @@ ippReadIO(void *src, /* I - Data source */
|
|
|
a9d1fb |
unsigned char *buffer, /* Data buffer */
|
|
|
a9d1fb |
string[IPP_MAX_TEXT],
|
|
|
a9d1fb |
/* Small string buffer */
|
|
|
a9d1fb |
- *bufptr; /* Pointer into buffer */
|
|
|
a9d1fb |
+ *bufptr, /* Pointer into buffer */
|
|
|
a9d1fb |
+ *bufend; /* End of buffer */
|
|
|
a9d1fb |
ipp_attribute_t *attr; /* Current attribute */
|
|
|
a9d1fb |
ipp_tag_t tag; /* Current tag */
|
|
|
a9d1fb |
ipp_tag_t value_tag; /* Current value tag */
|
|
|
a9d1fb |
@@ -3441,6 +3442,7 @@ ippReadIO(void *src, /* I - Data source */
|
|
|
a9d1fb |
}
|
|
|
a9d1fb |
|
|
|
a9d1fb |
bufptr = buffer;
|
|
|
a9d1fb |
+ bufend = buffer + n;
|
|
|
a9d1fb |
|
|
|
a9d1fb |
/*
|
|
|
a9d1fb |
* text-with-language and name-with-language are composite
|
|
|
a9d1fb |
@@ -3454,7 +3456,7 @@ ippReadIO(void *src, /* I - Data source */
|
|
|
a9d1fb |
|
|
|
a9d1fb |
n = (bufptr[0] << 8) | bufptr[1];
|
|
|
a9d1fb |
|
|
|
a9d1fb |
- if ((bufptr + 2 + n) >= (buffer + IPP_BUF_SIZE) || n >= (int)sizeof(string))
|
|
|
a9d1fb |
+ if ((bufptr + 2 + n + 2) > bufend || n >= (int)sizeof(string))
|
|
|
a9d1fb |
{
|
|
|
a9d1fb |
_cupsSetError(IPP_STATUS_ERROR_INTERNAL,
|
|
|
a9d1fb |
_("IPP language length overflows value."), 1);
|
|
|
a9d1fb |
@@ -3481,7 +3483,7 @@ ippReadIO(void *src, /* I - Data source */
|
|
|
a9d1fb |
bufptr += 2 + n;
|
|
|
a9d1fb |
n = (bufptr[0] << 8) | bufptr[1];
|
|
|
a9d1fb |
|
|
|
a9d1fb |
- if ((bufptr + 2 + n) >= (buffer + IPP_BUF_SIZE))
|
|
|
a9d1fb |
+ if ((bufptr + 2 + n) > bufend)
|
|
|
a9d1fb |
{
|
|
|
a9d1fb |
_cupsSetError(IPP_STATUS_ERROR_INTERNAL,
|
|
|
a9d1fb |
_("IPP string length overflows value."), 1);
|
|
|
a9d1fb |
|