Search
j0ke.net Open Build Service
>
Projects
>
home:netmax
:
monitoring
>
openssl1
> openssl-CVE-2016-0799.patch
Sign Up
|
Log In
Username
Password
Cancel
Overview
Repositories
Revisions
Requests
Users
Advanced
Attributes
Meta
File openssl-CVE-2016-0799.patch of Package openssl1
commit 578b956fe741bf8e84055547b1e83c28dd902c73 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> Index: openssl-1.0.1i/crypto/bio/b_print.c =================================================================== --- openssl-1.0.1i.orig/crypto/bio/b_print.c 2016-02-26 10:36:35.108070356 +0100 +++ openssl-1.0.1i/crypto/bio/b_print.c 2016-02-26 10:36:38.224094007 +0100 @@ -125,14 +125,14 @@ #define LLONG long #endif -static void fmtstr (char **, char **, size_t *, size_t *, +static int fmtstr (char **, char **, size_t *, size_t *, const char *, int, int, int); -static void fmtint (char **, char **, size_t *, size_t *, +static int fmtint (char **, char **, size_t *, size_t *, LLONG, int, int, int, int); -static void fmtfp (char **, char **, size_t *, size_t *, +static int 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, +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); @@ -165,7 +165,7 @@ #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, @@ -200,7 +200,8 @@ 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: @@ -306,8 +307,9 @@ 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; @@ -332,17 +334,19 @@ unsigned int); break; } - fmtint(sbuffer, buffer, &currlen, maxlen, value, + if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, ch == 'o' ? 8 : (ch == 'u' ? 10 : 16), - min, max, flags); + 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; @@ -361,8 +365,9 @@ 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 *); @@ -372,13 +377,15 @@ 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) { @@ -400,7 +407,8 @@ } 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 */ @@ -424,12 +432,13 @@ *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, @@ -440,36 +449,43 @@ 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, @@ -533,37 +549,45 @@ /* 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]); +{ + 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 @@ -597,7 +621,7 @@ return intpart; } -static void +static int fmtfp( char **sbuffer, char **buffer, @@ -682,47 +706,62 @@ 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]); +{ + 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]); +{ + 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, @@ -733,24 +772,30 @@ /* If we haven't at least one buffer, someone has doe a big booboo */ assert(*sbuffer != NULL || buffer != NULL); - if (buffer) { - while (*currlen >= *maxlen) { + /* |currlen| must always be <= |*maxlen| */ + assert(*currlen <= *maxlen); + + if (buffer && *currlen == *maxlen) { + if (*maxlen > INT_MAX - BUFFER_INC) + return 0; + + *maxlen += BUFFER_INC; if (*buffer == NULL) { - if (*maxlen == 0) - *maxlen = 1024; *buffer = OPENSSL_malloc(*maxlen); + if (*buffer == NULL) + return 0; if (*currlen > 0) { assert(*sbuffer != NULL); memcpy(*buffer, *sbuffer, *currlen); } *sbuffer = NULL; } else { - *maxlen += 1024; - *buffer = OPENSSL_realloc(*buffer, *maxlen); - } + char *tmpbuf; + tmpbuf = OPENSSL_realloc(*buffer, *maxlen); + if (tmpbuf == NULL) + return 0; + *buffer = tmpbuf; } - /* What to do if *buffer is NULL? */ - assert(*sbuffer != NULL || *buffer != NULL); } if (*currlen < *maxlen) { @@ -760,7 +805,7 @@ (*buffer)[(*currlen)++] = (char)c; } - return; + return 1; } /***************************************************************************/ @@ -792,8 +837,11 @@ 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); @@ -829,7 +877,8 @@ 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) /* In case of truncation, return -1 like traditional snprintf.