From 2c030c7a06e0c2b8227c7e85f5c58dfb339731d0 Mon Sep 17 00:00:00 2001 From: Michael R Sweet Date: Thu, 15 Aug 2019 14:06:47 -0400 Subject: [PATCH] Multiple security/disclosure issues: - CVE-2019-8696 and CVE-2019-8675: Fixed SNMP buffer overflows (rdar://51685251) - Fixed IPP buffer overflow (rdar://50035411) - Fixed memory disclosure issue in the scheduler (rdar://51373853) - Fixed DoS issues in the scheduler (rdar://51373929) diff --git a/cups/http.c b/cups/http.c index 266a15791..fbb1bf13c 100644 --- a/cups/http.c +++ b/cups/http.c @@ -1860,7 +1860,7 @@ httpPrintf(http_t *http, /* I - HTTP connection */ ...) /* I - Additional args as needed */ { ssize_t bytes; /* Number of bytes to write */ - char buf[16384]; /* Buffer for formatted string */ + char buf[65536]; /* Buffer for formatted string */ va_list ap; /* Variable argument pointer */ @@ -1872,7 +1872,12 @@ httpPrintf(http_t *http, /* I - HTTP connection */ DEBUG_printf(("3httpPrintf: (" CUPS_LLFMT " bytes) %s", CUPS_LLCAST bytes, buf)); - if (http->data_encoding == HTTP_ENCODING_FIELDS) + if (bytes > (ssize_t)(sizeof(buf) - 1)) + { + http->error = ENOMEM; + return (-1); + } + else if (http->data_encoding == HTTP_ENCODING_FIELDS) return ((int)httpWrite2(http, buf, (size_t)bytes)); else { diff --git a/cups/ipp.c b/cups/ipp.c index 6fae52a00..1bd59cef1 100644 --- a/cups/ipp.c +++ b/cups/ipp.c @@ -4550,9 +4550,7 @@ ippSetValueTag( break; case IPP_TAG_NAME : - if (temp_tag != IPP_TAG_KEYWORD && temp_tag != IPP_TAG_URI && - temp_tag != IPP_TAG_URISCHEME && temp_tag != IPP_TAG_LANGUAGE && - temp_tag != IPP_TAG_MIMETYPE) + if (temp_tag != IPP_TAG_KEYWORD) return (0); (*attr)->value_tag = (ipp_tag_t)(IPP_TAG_NAME | ((*attr)->value_tag & IPP_TAG_CUPS_CONST)); @@ -4560,10 +4558,7 @@ ippSetValueTag( case IPP_TAG_NAMELANG : case IPP_TAG_TEXTLANG : - if (value_tag == IPP_TAG_NAMELANG && - (temp_tag != IPP_TAG_NAME && temp_tag != IPP_TAG_KEYWORD && - temp_tag != IPP_TAG_URI && temp_tag != IPP_TAG_URISCHEME && - temp_tag != IPP_TAG_LANGUAGE && temp_tag != IPP_TAG_MIMETYPE)) + if (value_tag == IPP_TAG_NAMELANG && (temp_tag != IPP_TAG_NAME && temp_tag != IPP_TAG_KEYWORD)) return (0); if (value_tag == IPP_TAG_TEXTLANG && temp_tag != IPP_TAG_TEXT) diff --git a/cups/snmp.c b/cups/snmp.c index 5cefee454..1d9da01f2 100644 --- a/cups/snmp.c +++ b/cups/snmp.c @@ -1233,6 +1233,9 @@ asn1_get_integer( int value; /* Integer value */ + if (*buffer >= bufend) + return (0); + if (length > sizeof(int)) { (*buffer) += length; @@ -1259,6 +1262,9 @@ asn1_get_length(unsigned char **buffer, /* IO - Pointer in buffer */ unsigned length; /* Length */ + if (*buffer >= bufend) + return (0); + length = **buffer; (*buffer) ++; @@ -1301,6 +1307,9 @@ asn1_get_oid( int number; /* OID number */ + if (*buffer >= bufend) + return (0); + valend = *buffer + length; oidptr = oid; oidend = oid + oidsize - 1; @@ -1349,9 +1358,12 @@ asn1_get_packed( int value; /* Value */ + if (*buffer >= bufend) + return (0); + value = 0; - while ((**buffer & 128) && *buffer < bufend) + while (*buffer < bufend && (**buffer & 128)) { value = (value << 7) | (**buffer & 127); (*buffer) ++; @@ -1379,6 +1391,9 @@ asn1_get_string( char *string, /* I - String buffer */ size_t strsize) /* I - String buffer size */ { + if (*buffer >= bufend) + return (NULL); + if (length > (unsigned)(bufend - *buffer)) length = (unsigned)(bufend - *buffer); @@ -1421,6 +1436,9 @@ asn1_get_type(unsigned char **buffer, /* IO - Pointer in buffer */ int type; /* Type */ + if (*buffer >= bufend) + return (0); + type = **buffer; (*buffer) ++; diff --git a/scheduler/client.c b/scheduler/client.c index 923a6e67a..f693e7c49 100644 --- a/scheduler/client.c +++ b/scheduler/client.c @@ -564,6 +564,17 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ cupsdLogClient(con, CUPSD_LOG_DEBUG2, "cupsdReadClient: error=%d, used=%d, state=%s, data_encoding=HTTP_ENCODING_%s, data_remaining=" CUPS_LLFMT ", request=%p(%s), file=%d", httpError(con->http), (int)httpGetReady(con->http), httpStateString(httpGetState(con->http)), httpIsChunked(con->http) ? "CHUNKED" : "LENGTH", CUPS_LLCAST httpGetRemaining(con->http), con->request, con->request ? ippStateString(ippGetState(con->request)) : "", con->file); + if (httpError(con->http) == EPIPE && !httpGetReady(con->http) && recv(httpGetFd(con->http), buf, 1, MSG_PEEK) < 1) + { + /* + * Connection closed... + */ + + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Closing on EOF."); + cupsdCloseClient(con); + return; + } + if (httpGetState(con->http) == HTTP_STATE_GET_SEND || httpGetState(con->http) == HTTP_STATE_POST_SEND || httpGetState(con->http) == HTTP_STATE_STATUS) @@ -573,17 +584,6 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * connection and we need to shut it down... */ - if (!httpGetReady(con->http) && recv(httpGetFd(con->http), buf, 1, MSG_PEEK) < 1) - { - /* - * Connection closed... - */ - - cupsdLogClient(con, CUPSD_LOG_DEBUG, "Closing on EOF."); - cupsdCloseClient(con); - return; - } - cupsdLogClient(con, CUPSD_LOG_DEBUG, "Closing on unexpected HTTP read state %s.", httpStateString(httpGetState(con->http))); cupsdCloseClient(con); return; @@ -1950,6 +1950,7 @@ cupsdSendError(cupsd_client_t *con, /* I - Connection */ strlcpy(location, httpGetField(con->http, HTTP_FIELD_LOCATION), sizeof(location)); httpClearFields(con->http); + httpClearCookie(con->http); httpSetField(con->http, HTTP_FIELD_LOCATION, location); -- 2.21.0