Univention Bugzilla – Attachment 7512 Details for
Bug 40189
openssl: Denial of service (3.2)
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
CVE-2016-0799.patch
CVE-2016-0799.patch (text/plain), 14.99 KB, created by
Arvid Requate
on 2016-03-01 16:54 CET
(
hide
)
Description:
CVE-2016-0799.patch
Filename:
MIME Type:
Creator:
Arvid Requate
Created:
2016-03-01 16:54 CET
Size:
14.99 KB
patch
obsolete
>commit a801bf263849a2ef773e5bc0c86438cbba720835 >Author: Matt Caswell <matt@openssl.org> >Date: Thu Feb 25 13:09:46 2016 +0000 > > Fix memory issues in BIO_*printf functions > > The internal |fmtstr| function used in processing a "%s" format string > in the BIO_*printf functions could overflow while calculating the length > of a string and cause an OOB read when printing very long strings. > > Additionally the internal |doapr_outch| function can attempt to write to > an OOB memory location (at an offset from the NULL pointer) in the event of > a memory allocation failure. In 1.0.2 and below this could be caused where > the size of a buffer to be allocated is greater than INT_MAX. E.g. this > could be in processing a very long "%s" format string. Memory leaks can also > occur. > > These issues will only occur on certain platforms where sizeof(size_t) > > sizeof(int). E.g. many 64 bit systems. The first issue may mask the second > issue dependent on compiler behaviour. > > These problems could enable attacks where large amounts of untrusted data > is passed to the BIO_*printf functions. If applications use these functions > in this way then they could be vulnerable. OpenSSL itself uses these > functions when printing out human-readable dumps of ASN.1 data. Therefore > applications that print this data could be vulnerable if the data is from > untrusted sources. OpenSSL command line applications could also be > vulnerable where they print out ASN.1 data, or if untrusted data is passed > as command line arguments. > > Libssl is not considered directly vulnerable. Additionally certificates etc > received via remote connections via libssl are also unlikely to be able to > trigger these issues because of message size limits enforced within libssl. > > CVE-2016-0799 > > Issue reported by Guido Vranken. > > Reviewed-by: Andy Polyakov <appro@openssl.org> > (cherry picked from commit 578b956fe741bf8e84055547b1e83c28dd902c73) > >diff --git a/crypto/bio/b_print.c b/crypto/bio/b_print.c >index 7c81e25..90248fa 100644 >--- a/crypto/bio/b_print.c >+++ b/crypto/bio/b_print.c >@@ -125,16 +125,16 @@ > # define LLONG long > #endif > >-static void fmtstr(char **, char **, size_t *, size_t *, >- const char *, int, int, int); >-static void fmtint(char **, char **, size_t *, size_t *, >- LLONG, int, int, int, int); >-static void fmtfp(char **, char **, size_t *, size_t *, >- LDOUBLE, int, int, int); >-static void doapr_outch(char **, char **, size_t *, size_t *, int); >-static void _dopr(char **sbuffer, char **buffer, >- size_t *maxlen, size_t *retlen, int *truncated, >- const char *format, va_list args); >+static int fmtstr(char **, char **, size_t *, size_t *, >+ const char *, int, int, int); >+static int fmtint(char **, char **, size_t *, size_t *, >+ LLONG, int, int, int, int); >+static int fmtfp(char **, char **, size_t *, size_t *, >+ LDOUBLE, int, int, int); >+static int doapr_outch(char **, char **, size_t *, size_t *, int); >+static int _dopr(char **sbuffer, char **buffer, >+ size_t *maxlen, size_t *retlen, int *truncated, >+ const char *format, va_list args); > > /* format read states */ > #define DP_S_DEFAULT 0 >@@ -165,7 +165,7 @@ static void _dopr(char **sbuffer, char **buffer, > #define char_to_int(p) (p - '0') > #define OSSL_MAX(p,q) ((p >= q) ? p : q) > >-static void >+static int > _dopr(char **sbuffer, > char **buffer, > size_t *maxlen, >@@ -196,7 +196,8 @@ _dopr(char **sbuffer, > if (ch == '%') > state = DP_S_FLAGS; > else >- doapr_outch(sbuffer, buffer, &currlen, maxlen, ch); >+ if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) >+ return 0; > ch = *format++; > break; > case DP_S_FLAGS: >@@ -302,8 +303,9 @@ _dopr(char **sbuffer, > value = va_arg(args, int); > break; > } >- fmtint(sbuffer, buffer, &currlen, maxlen, >- value, 10, min, max, flags); >+ if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min, >+ max, flags)) >+ return 0; > break; > case 'X': > flags |= DP_F_UP; >@@ -326,17 +328,19 @@ _dopr(char **sbuffer, > value = (LLONG) va_arg(args, unsigned int); > break; > } >- fmtint(sbuffer, buffer, &currlen, maxlen, value, >- ch == 'o' ? 8 : (ch == 'u' ? 10 : 16), >- min, max, flags); >+ if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, >+ ch == 'o' ? 8 : (ch == 'u' ? 10 : 16), >+ min, max, flags)) >+ return 0; > break; > case 'f': > if (cflags == DP_C_LDOUBLE) > fvalue = va_arg(args, LDOUBLE); > else > fvalue = va_arg(args, double); >- fmtfp(sbuffer, buffer, &currlen, maxlen, >- fvalue, min, max, flags); >+ if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, >+ flags)) >+ return 0; > break; > case 'E': > flags |= DP_F_UP; >@@ -355,8 +359,9 @@ _dopr(char **sbuffer, > fvalue = va_arg(args, double); > break; > case 'c': >- doapr_outch(sbuffer, buffer, &currlen, maxlen, >- va_arg(args, int)); >+ if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, >+ va_arg(args, int))) >+ return 0; > break; > case 's': > strvalue = va_arg(args, char *); >@@ -366,13 +371,15 @@ _dopr(char **sbuffer, > else > max = *maxlen; > } >- fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue, >- flags, min, max); >+ if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue, >+ flags, min, max)) >+ return 0; > break; > case 'p': > value = (long)va_arg(args, void *); >- fmtint(sbuffer, buffer, &currlen, maxlen, >- value, 16, min, max, flags | DP_F_NUM); >+ if (!fmtint(sbuffer, buffer, &currlen, maxlen, >+ value, 16, min, max, flags | DP_F_NUM)) >+ return 0; > break; > case 'n': /* XXX */ > if (cflags == DP_C_SHORT) { >@@ -394,7 +401,8 @@ _dopr(char **sbuffer, > } > break; > case '%': >- doapr_outch(sbuffer, buffer, &currlen, maxlen, ch); >+ if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) >+ return 0; > break; > case 'w': > /* not supported yet, treat as next char */ >@@ -418,46 +426,56 @@ _dopr(char **sbuffer, > *truncated = (currlen > *maxlen - 1); > if (*truncated) > currlen = *maxlen - 1; >- doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0'); >+ if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0')) >+ return 0; > *retlen = currlen - 1; >- return; >+ return 1; > } > >-static void >+static int > fmtstr(char **sbuffer, > char **buffer, > size_t *currlen, > size_t *maxlen, const char *value, int flags, int min, int max) > { >- int padlen, strln; >+ int padlen; >+ size_t strln; > int cnt = 0; > > if (value == 0) > value = "<NULL>"; >- for (strln = 0; value[strln]; ++strln) ; >+ >+ strln = strlen(value); >+ if (strln > INT_MAX) >+ strln = INT_MAX; >+ > padlen = min - strln; >- if (padlen < 0) >+ if (min < 0 || padlen < 0) > padlen = 0; > if (flags & DP_F_MINUS) > padlen = -padlen; > > while ((padlen > 0) && (cnt < max)) { >- doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); >+ if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) >+ return 0; > --padlen; > ++cnt; > } > while (*value && (cnt < max)) { >- doapr_outch(sbuffer, buffer, currlen, maxlen, *value++); >+ if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++)) >+ return 0; > ++cnt; > } > while ((padlen < 0) && (cnt < max)) { >- doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); >+ if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) >+ return 0; > ++padlen; > ++cnt; > } >+ return 1; > } > >-static void >+static int > fmtint(char **sbuffer, > char **buffer, > size_t *currlen, >@@ -517,37 +535,44 @@ fmtint(char **sbuffer, > > /* spaces */ > while (spadlen > 0) { >- doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); >+ if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) >+ return 0; > --spadlen; > } > > /* sign */ > if (signvalue) >- doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); >+ if(!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) >+ return 0; > > /* prefix */ > while (*prefix) { >- doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix); >+ if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix)) >+ return 0; > prefix++; > } > > /* zeros */ > if (zpadlen > 0) { > while (zpadlen > 0) { >- doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); >+ if(!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) >+ return 0; > --zpadlen; > } > } > /* digits */ >- while (place > 0) >- doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]); >+ while (place > 0) { >+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place])) >+ return 0; >+ } > > /* left justified spaces */ > while (spadlen < 0) { >- doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); >+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) >+ return 0; > ++spadlen; > } >- return; >+ return 1; > } > > static LDOUBLE abs_val(LDOUBLE value) >@@ -578,7 +603,7 @@ static long roundv(LDOUBLE value) > return intpart; > } > >-static void >+static int > fmtfp(char **sbuffer, > char **buffer, > size_t *currlen, >@@ -657,47 +682,61 @@ fmtfp(char **sbuffer, > > if ((flags & DP_F_ZERO) && (padlen > 0)) { > if (signvalue) { >- doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); >+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) >+ return 0; > --padlen; > signvalue = 0; > } > while (padlen > 0) { >- doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); >+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) >+ return 0; > --padlen; > } > } > while (padlen > 0) { >- doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); >+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) >+ return 0; > --padlen; > } >- if (signvalue) >- doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); >+ if (signvalue && !doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) >+ return 0; > >- while (iplace > 0) >- doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]); >+ while (iplace > 0) { >+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace])) >+ return 0; >+ } > > /* > * Decimal point. This should probably use locale to find the correct > * char to print out. > */ > if (max > 0 || (flags & DP_F_NUM)) { >- doapr_outch(sbuffer, buffer, currlen, maxlen, '.'); >+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.')) >+ return 0; > >- while (fplace > 0) >- doapr_outch(sbuffer, buffer, currlen, maxlen, fconvert[--fplace]); >+ while (fplace > 0) { >+ if(!doapr_outch(sbuffer, buffer, currlen, maxlen, >+ fconvert[--fplace])) >+ return 0; >+ } > } > while (zpadlen > 0) { >- doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); >+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) >+ return 0; > --zpadlen; > } > > while (padlen < 0) { >- doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); >+ if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) >+ return 0; > ++padlen; > } >+ return 1; > } > >-static void >+#define BUFFER_INC 1024 >+ >+static int > doapr_outch(char **sbuffer, > char **buffer, size_t *currlen, size_t *maxlen, int c) > { >@@ -708,24 +747,25 @@ doapr_outch(char **sbuffer, > assert(*currlen <= *maxlen); > > if (buffer && *currlen == *maxlen) { >- *maxlen += 1024; >+ if (*maxlen > INT_MAX - BUFFER_INC) >+ return 0; >+ >+ *maxlen += BUFFER_INC; > if (*buffer == NULL) { > *buffer = OPENSSL_malloc(*maxlen); >- if (!*buffer) { >- /* Panic! Can't really do anything sensible. Just return */ >- return; >- } >+ if (*buffer == NULL) >+ return 0; > if (*currlen > 0) { > assert(*sbuffer != NULL); > memcpy(*buffer, *sbuffer, *currlen); > } > *sbuffer = NULL; > } else { >- *buffer = OPENSSL_realloc(*buffer, *maxlen); >- if (!*buffer) { >- /* Panic! Can't really do anything sensible. Just return */ >- return; >- } >+ char *tmpbuf; >+ tmpbuf = OPENSSL_realloc(*buffer, *maxlen); >+ if (tmpbuf == NULL) >+ return 0; >+ *buffer = tmpbuf; > } > } > >@@ -736,7 +776,7 @@ doapr_outch(char **sbuffer, > (*buffer)[(*currlen)++] = (char)c; > } > >- return; >+ return 1; > } > > /***************************************************************************/ >@@ -768,7 +808,11 @@ int BIO_vprintf(BIO *bio, const char *format, va_list args) > > dynbuf = NULL; > CRYPTO_push_info("doapr()"); >- _dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format, args); >+ if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format, >+ args)) { >+ OPENSSL_free(dynbuf); >+ return -1; >+ } > if (dynbuf) { > ret = BIO_write(bio, dynbuf, (int)retlen); > OPENSSL_free(dynbuf); >@@ -803,7 +847,8 @@ int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) > size_t retlen; > int truncated; > >- _dopr(&buf, NULL, &n, &retlen, &truncated, format, args); >+ if(!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args)) >+ return -1; > > if (truncated) > /*
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
Actions:
View
|
Diff
Attachments on
bug 40189
:
7509
|
7510
|
7511
| 7512 |
7513