Meshed up: https://github.com/p11-glue/p11-kit/commit/bb3a3cb1cb4ae8341fa1cf1cc4e9f282c7c74b76 https://github.com/p11-glue/p11-kit/commit/69d751ca9df9ac101adfb1e5aa7e83e3358106ba https://github.com/p11-glue/p11-kit/commit/7625cfcebccf1c02d17e9295e1d883ea688ea264 https://github.com/p11-glue/p11-kit/commit/6c1c94bd2360f5778beb397ba5508d5084b7f0ee https://github.com/p11-glue/p11-kit/commit/7f032183dfd36c1f91d2400ceb5bbc90376a310c Should fix CVE-2020-29361 CVE-2020-29362 CVE-2020-29363 diff --git a/common/compat.c b/common/compat.c index 8b14658..3570770 100644 --- a/common/compat.c +++ b/common/compat.c @@ -496,8 +496,8 @@ reallocarray (void *ptr, size_t nmemb, size_t size) { - assert (nmemb > 0 && size > 0); - if (SIZE_MAX / nmemb < size) { + assert (nmemb >= 0 && size >= 0); + if (nmemb != 0 && SIZE_MAX / nmemb < size) { errno = ENOMEM; return NULL; } diff --git a/p11-kit/iter.c b/p11-kit/iter.c index d26cd71..766dd9a 100644 --- a/p11-kit/iter.c +++ b/p11-kit/iter.c @@ -545,7 +545,7 @@ move_next_session (P11KitIter *iter) if (rv != CKR_OK) return finish_iterating (iter, rv); - iter->slots = realloc (iter->slots, sizeof (CK_SLOT_ID) * (num_slots + 1)); + iter->slots = reallocarray (iter->slots, num_slots + 1, sizeof (CK_SLOT_ID)); return_val_if_fail (iter->slots != NULL, CKR_HOST_MEMORY); rv = (iter->module->C_GetSlotList) (CK_TRUE, iter->slots, &num_slots); @@ -698,7 +698,7 @@ p11_kit_iter_next (P11KitIter *iter) for (;;) { if (iter->max_objects - iter->num_objects == 0) { iter->max_objects = iter->max_objects ? iter->max_objects * 2 : 64; - iter->objects = realloc (iter->objects, iter->max_objects * sizeof (CK_ULONG)); + iter->objects = reallocarray (iter->objects, iter->max_objects, sizeof (CK_ULONG)); return_val_if_fail (iter->objects != NULL, CKR_HOST_MEMORY); } diff --git a/p11-kit/lists.c b/p11-kit/lists.c index 5804be2..365a6d8 100644 --- a/p11-kit/lists.c +++ b/p11-kit/lists.c @@ -64,6 +64,8 @@ hex_encode (const unsigned char *data, size_t i; size_t o; + if ((SIZE_MAX - 1) / 3 < n_data) + return NULL; result = malloc (n_data * 3 + 1); if (result == NULL) return NULL; diff --git a/p11-kit/log.c b/p11-kit/log.c index 19377b2..58bc5f4 100644 --- a/p11-kit/log.c +++ b/p11-kit/log.c @@ -726,7 +726,7 @@ log_token_info (p11_buffer *buf, (unsigned int)info->firmwareVersion.minor); p11_buffer_add (buf, temp, -1); p11_buffer_add (buf, "\n\tutcTime: ", -1); - p11_buffer_add (buf, (info->flags & CKF_CLOCK_ON_TOKEN) ? (const char*)info->utcTime : "", -1); + p11_buffer_add (buf, (info->flags & CKF_CLOCK_ON_TOKEN) ? (const char*)info->utcTime : "", sizeof (info->utcTime)); p11_buffer_add (buf, "\n }\n", -1); } } diff --git a/p11-kit/proxy.c b/p11-kit/proxy.c index 643bf4e..8066c84 100644 --- a/p11-kit/proxy.c +++ b/p11-kit/proxy.c @@ -278,7 +278,7 @@ proxy_list_slots (Proxy *py, Mapping *mappings, unsigned int n_mappings) return_val_if_fail (count == 0 || slots != NULL, CKR_GENERAL_ERROR); if (count > 0) { - py->mappings = realloc (py->mappings, sizeof (Mapping) * (py->n_mappings + count)); + py->mappings = reallocarray (py->mappings, (py->n_mappings + count), sizeof (Mapping)); return_val_if_fail (py->mappings != NULL, CKR_HOST_MEMORY); /* And now add a mapping for each of those slots */ diff --git a/p11-kit/rpc-message.c b/p11-kit/rpc-message.c index 672d1c7..fad569e 100644 --- a/p11-kit/rpc-message.c +++ b/p11-kit/rpc-message.c @@ -43,6 +43,7 @@ #include "rpc-message.h" #include +#include #include #define ELEMS(x) (sizeof (x) / sizeof (x[0])) @@ -114,6 +115,18 @@ p11_rpc_message_alloc_extra (p11_rpc_message *msg, return (void *)(data + 1); } +void * +p11_rpc_message_alloc_extra_array (p11_rpc_message *msg, + size_t nmemb, + size_t size) +{ + if (nmemb != 0 && (SIZE_MAX - sizeof (void *)) / nmemb < size) { + errno = ENOMEM; + return NULL; + } + return p11_rpc_message_alloc_extra (msg, nmemb * size); +} + bool p11_rpc_message_prep (p11_rpc_message *msg, int call_id, @@ -744,7 +757,7 @@ p11_rpc_buffer_get_byte_array (p11_buffer *buf, return false; } - if (buf->len < len || *offset > buf->len - len) { + if (buf->len < len || off > buf->len - len) { p11_buffer_fail (buf); return false; } @@ -1212,7 +1225,7 @@ p11_rpc_buffer_get_attribute (p11_buffer *buffer, size_t *offset, CK_ATTRIBUTE *attr) { - uint32_t type, length; + uint32_t type, length, decode_length; unsigned char validity; p11_rpc_attribute_serializer *serializer; p11_rpc_value_type value_type; @@ -1242,8 +1255,13 @@ p11_rpc_buffer_get_attribute (p11_buffer *buffer, assert (serializer != NULL); if (!serializer->decode (buffer, offset, attr->pValue, &attr->ulValueLen)) return false; - if (!attr->pValue) + if (!attr->pValue) { + decode_length = attr->ulValueLen; attr->ulValueLen = length; + if (decode_length > length) { + return false; + } + } attr->type = type; return true; } diff --git a/p11-kit/rpc-message.h b/p11-kit/rpc-message.h index 989bbc0..62e7b18 100644 --- a/p11-kit/rpc-message.h +++ b/p11-kit/rpc-message.h @@ -255,6 +255,10 @@ void p11_rpc_message_clear (p11_rpc_message *msg); void * p11_rpc_message_alloc_extra (p11_rpc_message *msg, size_t length); +void * p11_rpc_message_alloc_extra_array (p11_rpc_message *msg, + size_t nmemb, + size_t size); + bool p11_rpc_message_prep (p11_rpc_message *msg, int call_id, p11_rpc_message_type type); diff --git a/p11-kit/rpc-server.c b/p11-kit/rpc-server.c index 846ee94..dfdb76d 100644 --- a/p11-kit/rpc-server.c +++ b/p11-kit/rpc-server.c @@ -88,7 +88,7 @@ proto_read_byte_buffer (p11_rpc_message *msg, if (length == 0) return CKR_OK; - *buffer = p11_rpc_message_alloc_extra (msg, length * sizeof (CK_BYTE)); + *buffer = p11_rpc_message_alloc_extra_array (msg, length, sizeof (CK_BYTE)); if (*buffer == NULL) return CKR_DEVICE_MEMORY; @@ -186,7 +186,7 @@ proto_read_ulong_buffer (p11_rpc_message *msg, if (length == 0) return CKR_OK; - *buffer = p11_rpc_message_alloc_extra (msg, length * sizeof (CK_ULONG)); + *buffer = p11_rpc_message_alloc_extra_array (msg, length, sizeof (CK_ULONG)); if (!*buffer) return CKR_DEVICE_MEMORY; @@ -246,7 +246,7 @@ proto_read_attribute_buffer (p11_rpc_message *msg, return PARSE_ERROR; /* Allocate memory for the attribute structures */ - attrs = p11_rpc_message_alloc_extra (msg, n_attrs * sizeof (CK_ATTRIBUTE)); + attrs = p11_rpc_message_alloc_extra_array (msg, n_attrs, sizeof (CK_ATTRIBUTE)); if (attrs == NULL) return CKR_DEVICE_MEMORY; @@ -300,7 +300,7 @@ proto_read_attribute_array (p11_rpc_message *msg, return PARSE_ERROR; /* Allocate memory for the attribute structures */ - attrs = p11_rpc_message_alloc_extra (msg, n_attrs * sizeof (CK_ATTRIBUTE)); + attrs = p11_rpc_message_alloc_extra_array (msg, n_attrs, sizeof (CK_ATTRIBUTE)); if (attrs == NULL) return CKR_DEVICE_MEMORY; diff --git a/trust/index.c b/trust/index.c index 2d1da29..795c67f 100644 --- a/trust/index.c +++ b/trust/index.c @@ -271,7 +271,7 @@ bucket_insert (index_bucket *bucket, if (bucket->num + 1 > alloc) { alloc = alloc ? alloc * 2 : 1; return_if_fail (alloc != 0); - bucket->elem = realloc (bucket->elem, alloc * sizeof (CK_OBJECT_HANDLE)); + bucket->elem = reallocarray (bucket->elem, alloc, sizeof (CK_OBJECT_HANDLE)); } return_if_fail (bucket->elem != NULL); @@ -291,7 +291,7 @@ bucket_push (index_bucket *bucket, if (bucket->num + 1 > alloc) { alloc = alloc ? alloc * 2 : 1; return_val_if_fail (alloc != 0, false); - bucket->elem = realloc (bucket->elem, alloc * sizeof (CK_OBJECT_HANDLE)); + bucket->elem = reallocarray (bucket->elem, alloc, sizeof (CK_OBJECT_HANDLE)); } return_val_if_fail (bucket->elem != NULL, false);