Description: CVE-2015-2806: stack overflow in asn1_der_decoding Origin: backport, http://git.savannah.gnu.org/gitweb/?p=libtasn1.git;a=commit;h=e47b2a0651ffe1867c844968ade7f6127957bf13, http://git.savannah.gnu.org/gitweb/?p=libtasn1.git;a=commit;h=4d4f992826a4962790ecd0cce6fbba4a415ce149 Bug-SuSE: https://bugzilla.novell.com/show_bug.cgi?id=924828 Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=1207192 Forwarded: not-needed Author: Salvatore Bonaccorso Last-Update: 2015-04-11 Applied-Upstream: 4.4 --- a/lib/coding.c +++ b/lib/coding.c @@ -34,6 +34,11 @@ #define MAX_TAG_LEN 16 +/* MAX(a,b) returns the maximum of A and B. */ +#ifndef MAX +# define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + /******************************************************/ /* Function : _asn1_error_description_value_not_found */ /* Description: creates the ErrorDescription string */ @@ -451,7 +456,7 @@ _asn1_insert_tag_der (ASN1_TYPE node, un { ASN1_TYPE p; int tag_len, is_tag_implicit; - unsigned char class, class_implicit = 0, temp[SIZEOF_UNSIGNED_INT * 3 + 1]; + unsigned char class, class_implicit = 0, temp[MAX(SIZEOF_UNSIGNED_INT * 3 + 1, LTOSTR_MAX_SIZE)]; unsigned long tag_implicit = 0; unsigned char tag_der[MAX_TAG_LEN]; @@ -871,7 +876,7 @@ asn1_der_coding (ASN1_TYPE element, cons char *ErrorDescription) { ASN1_TYPE node, p, p2; - unsigned char temp[SIZEOF_UNSIGNED_LONG_INT * 3 + 1]; + unsigned char temp[MAX(LTOSTR_MAX_SIZE, SIZEOF_UNSIGNED_LONG_INT * 3 + 1)]; int counter, counter_old, len2, len3, tlen, move, max_len, max_len_old; asn1_retCode err; unsigned char *der = ider; --- a/lib/parser_aux.c +++ b/lib/parser_aux.c @@ -579,10 +579,10 @@ _asn1_delete_list_and_nodes (void) char * -_asn1_ltostr (long v, char *str) +_asn1_ltostr (long v, char str[LTOSTR_MAX_SIZE]) { long d, r; - char temp[20]; + char temp[LTOSTR_MAX_SIZE]; int count, k, start; if (v < 0) @@ -603,7 +603,7 @@ _asn1_ltostr (long v, char *str) count++; v = d; } - while (v); + while (v && ((start+count) < LTOSTR_MAX_SIZE-1)); for (k = 0; k < count; k++) str[k + start] = temp[start + count - k - 1]; --- a/lib/parser_aux.h +++ b/lib/parser_aux.h @@ -62,7 +62,9 @@ void _asn1_delete_list (void); void _asn1_delete_list_and_nodes (void); -char *_asn1_ltostr (long v, char *str); +/* Max 64-bit integer length is 20 chars + 1 for sign + 1 for null termination */ +#define LTOSTR_MAX_SIZE 22 +char *_asn1_ltostr (long v, char str[LTOSTR_MAX_SIZE]); ASN1_TYPE _asn1_find_up (ASN1_TYPE node); --- a/lib/decoding.c +++ b/lib/decoding.c @@ -276,7 +276,7 @@ _asn1_get_objectid_der (const unsigned c { int len_len, len, k; int leading; - char temp[20]; + char temp[LTOSTR_MAX_SIZE]; unsigned long val, val1, prev_val; *ret_len = 0; --- a/lib/element.c +++ b/lib/element.c @@ -133,7 +133,7 @@ int _asn1_append_sequence_set (ASN1_TYPE node) { ASN1_TYPE p, p2; - char temp[10]; + char temp[LTOSTR_MAX_SIZE]; long n; if (!node || !(node->down))