From 189cd946f4c9c560abf4830f7ad47559d029619f Mon Sep 17 00:00:00 2001 From: zou_lin77 <422351577@qq.com> Date: Sat, 9 Jan 2021 17:17:42 +0800 Subject: [PATCH] fix CVE-2020-29361 CVE-2020-29362 CVE-2020-29363 --- ...ithmetic-overflows-before-allocating.patch | 174 ++++++++++++++++++ ...Follow-up-to-arithmetic-overflow-fix.patch | 45 +++++ ...eck-in-p11_rpc_buffer_get_byte_array.patch | 29 +++ ...attribute-length-against-buffer-size.patch | 44 +++++ ...ot-ID-reuse-avoiding-duplicating-IDs.patch | 129 +++++++++++++ p11-kit.spec | 11 +- 6 files changed, 431 insertions(+), 1 deletion(-) create mode 100644 backport-0001-CVE-2020-29361-Check-for-arithmetic-overflows-before-allocating.patch create mode 100644 backport-0002-CVE-2020-29361-Follow-up-to-arithmetic-overflow-fix.patch create mode 100644 backport-CVE-2020-29362-Fix-bounds-check-in-p11_rpc_buffer_get_byte_array.patch create mode 100644 backport-CVE-2020-29363-Check-attribute-length-against-buffer-size.patch create mode 100644 backport-proxy-Fix-slot-ID-reuse-avoiding-duplicating-IDs.patch diff --git a/backport-0001-CVE-2020-29361-Check-for-arithmetic-overflows-before-allocating.patch b/backport-0001-CVE-2020-29361-Check-for-arithmetic-overflows-before-allocating.patch new file mode 100644 index 0000000..c270f75 --- /dev/null +++ b/backport-0001-CVE-2020-29361-Check-for-arithmetic-overflows-before-allocating.patch @@ -0,0 +1,174 @@ +From 5307a1d21a50cacd06f471a873a018d23ba4b963 Mon Sep 17 00:00:00 2001 +From: David Cook +Date: Sat, 7 Nov 2020 10:12:44 -0600 +Subject: [PATCH] Check for arithmetic overflows before allocating + +--- + p11-kit/iter.c | 4 ++-- + p11-kit/lists.c | 2 ++ + p11-kit/proxy.c | 2 +- + p11-kit/rpc-message.c | 13 +++++++++++++ + p11-kit/rpc-message.h | 4 ++++ + p11-kit/rpc-server.c | 8 ++++---- + trust/index.c | 4 ++-- + 7 files changed, 28 insertions(+), 9 deletions(-) + +diff --git a/p11-kit/iter.c b/p11-kit/iter.c +index b5a9bbf..d8c8207 100644 +--- a/p11-kit/iter.c ++++ b/p11-kit/iter.c +@@ -549,7 +549,7 @@ move_next_session (P11KitIter *iter) + if (rv != CKR_OK) + return finish_iterating (iter, rv); + +- slots = realloc (iter->slots, sizeof (CK_SLOT_ID) * (num_slots + 1)); ++ slots = reallocarray (iter->slots, num_slots + 1, sizeof (CK_SLOT_ID)); + return_val_if_fail (slots != NULL, CKR_HOST_MEMORY); + iter->slots = slots; + +@@ -705,7 +705,7 @@ p11_kit_iter_next (P11KitIter *iter) + CK_OBJECT_HANDLE *objects; + + iter->max_objects = iter->max_objects ? iter->max_objects * 2 : 64; +- objects = realloc (iter->objects, iter->max_objects * sizeof (CK_ULONG)); ++ objects = reallocarray (iter->objects, iter->max_objects, sizeof (CK_ULONG)); + return_val_if_fail (objects != NULL, CKR_HOST_MEMORY); + iter->objects = objects; + } +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/proxy.c b/p11-kit/proxy.c +index df18ac0..d24e977 100644 +--- a/p11-kit/proxy.c ++++ b/p11-kit/proxy.c +@@ -283,7 +283,7 @@ proxy_list_slots (Proxy *py, Mapping *mappings, unsigned int n_mappings) + + new_slots = calloc (count, sizeof(CK_SLOT_ID)); + return_val_if_fail (new_slots != NULL, CKR_HOST_MEMORY); +- new_mappings = realloc (py->mappings, sizeof (Mapping) * (py->n_mappings + count)); ++ new_mappings = reallocarray (py->mappings, (py->n_mappings + count), sizeof (Mapping)); + return_val_if_fail (new_mappings != NULL, CKR_HOST_MEMORY); + py->mappings = new_mappings; + +diff --git a/p11-kit/rpc-message.c b/p11-kit/rpc-message.c +index 2128358..875adaf 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 ((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, +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 27b9717..a57f7ec 100644 +--- a/trust/index.c ++++ b/trust/index.c +@@ -273,7 +273,7 @@ bucket_insert (index_bucket *bucket, + + alloc = alloc ? alloc * 2 : 1; + return_if_fail (alloc != 0); +- elem = realloc (bucket->elem, alloc * sizeof (CK_OBJECT_HANDLE)); ++ elem = reallocarray (bucket->elem, alloc, sizeof (CK_OBJECT_HANDLE)); + return_if_fail (elem != NULL); + bucket->elem = elem; + } +@@ -297,7 +297,7 @@ bucket_push (index_bucket *bucket, + + alloc = alloc ? alloc * 2 : 1; + return_val_if_fail (alloc != 0, false); +- elem = realloc (bucket->elem, alloc * sizeof (CK_OBJECT_HANDLE)); ++ elem = reallocarray (bucket->elem, alloc, sizeof (CK_OBJECT_HANDLE)); + return_val_if_fail (elem != NULL, false); + bucket->elem = elem; + } +-- +1.8.3.1 + diff --git a/backport-0002-CVE-2020-29361-Follow-up-to-arithmetic-overflow-fix.patch b/backport-0002-CVE-2020-29361-Follow-up-to-arithmetic-overflow-fix.patch new file mode 100644 index 0000000..4167277 --- /dev/null +++ b/backport-0002-CVE-2020-29361-Follow-up-to-arithmetic-overflow-fix.patch @@ -0,0 +1,45 @@ +From bd670b1d4984b27d6a397b9ddafaf89ab26e4e7f Mon Sep 17 00:00:00 2001 +From: David Cook +Date: Sat, 14 Nov 2020 13:10:29 -0600 +Subject: [PATCH] Follow-up to arithmetic overflow fix + +Check if nmemb is zero in p11_rpc_message_alloc_extra_array to avoid a +division by zero trap. Additionally, change the reallocarray +compatibility shim so that it won't assert when resizing an array to +zero, and add the same nmemb != 0 check there. +--- + common/compat.c | 4 ++-- + p11-kit/rpc-message.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/common/compat.c b/common/compat.c +index be7e9e6..4390cef 100644 +--- a/common/compat.c ++++ b/common/compat.c +@@ -525,8 +525,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/rpc-message.c b/p11-kit/rpc-message.c +index 875adaf..8dfa30b 100644 +--- a/p11-kit/rpc-message.c ++++ b/p11-kit/rpc-message.c +@@ -120,7 +120,7 @@ p11_rpc_message_alloc_extra_array (p11_rpc_message *msg, + size_t nmemb, + size_t size) + { +- if ((SIZE_MAX - sizeof (void *)) / nmemb < size) { ++ if (nmemb != 0 && (SIZE_MAX - sizeof (void *)) / nmemb < size) { + errno = ENOMEM; + return NULL; + } +-- +1.8.3.1 + diff --git a/backport-CVE-2020-29362-Fix-bounds-check-in-p11_rpc_buffer_get_byte_array.patch b/backport-CVE-2020-29362-Fix-bounds-check-in-p11_rpc_buffer_get_byte_array.patch new file mode 100644 index 0000000..bb2d63f --- /dev/null +++ b/backport-CVE-2020-29362-Fix-bounds-check-in-p11_rpc_buffer_get_byte_array.patch @@ -0,0 +1,29 @@ +From bda2f543ff8e0195c90e849379ef1585d00677bc Mon Sep 17 00:00:00 2001 +From: David Cook +Date: Fri, 6 Nov 2020 23:42:38 -0600 +Subject: [PATCH] Fix bounds check in p11_rpc_buffer_get_byte_array + +This bounds check should be using off, not *offset, because it has been +advanced four bytes from reading a uint32 earlier in the function. +Additionally, the pointer that is returned is computed using off, not +*offset. +--- + p11-kit/rpc-message.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/p11-kit/rpc-message.c b/p11-kit/rpc-message.c +index be45c18..b26b036 100644 +--- a/p11-kit/rpc-message.c ++++ b/p11-kit/rpc-message.c +@@ -744,7 +744,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; + } +-- +1.8.3.1 + diff --git a/backport-CVE-2020-29363-Check-attribute-length-against-buffer-size.patch b/backport-CVE-2020-29363-Check-attribute-length-against-buffer-size.patch new file mode 100644 index 0000000..cdb6423 --- /dev/null +++ b/backport-CVE-2020-29363-Check-attribute-length-against-buffer-size.patch @@ -0,0 +1,44 @@ +From 2617f3ef888e103324a28811886b99ed0a56346d Mon Sep 17 00:00:00 2001 +From: David Cook +Date: Sat, 7 Nov 2020 00:06:01 -0600 +Subject: [PATCH] Check attribute length against buffer size + +If an attribute's length does not match the length of the byte array +inside it, one length was used for allocation, and the other was used +for memcpy. This additional check will instead return an error on +malformed messages. +--- + p11-kit/rpc-message.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/p11-kit/rpc-message.c b/p11-kit/rpc-message.c +index b26b036..2128358 100644 +--- a/p11-kit/rpc-message.c ++++ b/p11-kit/rpc-message.c +@@ -1213,7 +1213,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; +@@ -1243,8 +1243,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; + } +-- +1.8.3.1 + diff --git a/backport-proxy-Fix-slot-ID-reuse-avoiding-duplicating-IDs.patch b/backport-proxy-Fix-slot-ID-reuse-avoiding-duplicating-IDs.patch new file mode 100644 index 0000000..e5fef92 --- /dev/null +++ b/backport-proxy-Fix-slot-ID-reuse-avoiding-duplicating-IDs.patch @@ -0,0 +1,129 @@ +From c8f8053edc9098fdb36fbb34165b8d92ed596798 Mon Sep 17 00:00:00 2001 +From: Anderson Toshiyuki Sasaki +Date: Mon, 17 Feb 2020 19:29:43 +0100 +Subject: [PATCH] proxy: Fix slot ID reuse, avoiding duplicating IDs + +Previously, when re-mapping the slots, a slot ID could be assigned to +more than one device, causing errors when searching for the right +mapping (it would use the first found). + +Also assign new slot IDs for new found slots, avoiding previously used +slot IDs. The last assigned slot ID is stored in the proxy structure +in a new added field last_id. + +Signed-off-by: Anderson Toshiyuki Sasaki +--- + p11-kit/proxy.c | 56 +++++++++++++++++++++++++++++++++++++------------------- + 1 file changed, 37 insertions(+), 19 deletions(-) + +diff --git a/p11-kit/proxy.c b/p11-kit/proxy.c +index 74ba38f..97c9b09 100644 +--- a/p11-kit/proxy.c ++++ b/p11-kit/proxy.c +@@ -83,6 +83,7 @@ typedef struct { + p11_dict *sessions; + CK_FUNCTION_LIST **inited; + unsigned int forkid; ++ CK_SLOT_ID last_id; + } Proxy; + + typedef struct _State { +@@ -113,22 +114,20 @@ map_slot_unlocked (Proxy *px, + CK_SLOT_ID slot, + Mapping *mapping) + { ++ unsigned int i; ++ + assert (px != NULL); + assert (mapping != NULL); + +- if (slot < MAPPING_OFFSET) +- return CKR_SLOT_ID_INVALID; +- slot -= MAPPING_OFFSET; +- +- if (slot > px->n_mappings) { +- return CKR_SLOT_ID_INVALID; +- } else if (px->n_mappings == 0) { +- return CKR_SLOT_ID_INVALID; +- } else { +- assert (px->mappings); +- memcpy (mapping, &px->mappings[slot], sizeof (Mapping)); +- return CKR_OK; ++ for (i = 0; i < px->n_mappings; i++) { ++ assert (px->mappings != NULL); ++ if (px->mappings[i].wrap_slot == slot) { ++ memcpy (mapping, &px->mappings[i], sizeof(Mapping)); ++ return CKR_OK; ++ } + } ++ ++ return CKR_SLOT_ID_INVALID; + } + + static CK_RV +@@ -279,29 +278,47 @@ proxy_list_slots (Proxy *py, Mapping *mappings, unsigned int n_mappings) + + if (count > 0) { + Mapping *new_mappings; ++ CK_SLOT_ID_PTR new_slots; ++ int new_slots_count = 0; + ++ new_slots = calloc (count, sizeof(CK_SLOT_ID)); ++ return_val_if_fail (new_slots != NULL, CKR_HOST_MEMORY); + new_mappings = realloc (py->mappings, sizeof (Mapping) * (py->n_mappings + count)); + return_val_if_fail (new_mappings != NULL, CKR_HOST_MEMORY); + py->mappings = new_mappings; + +- /* And now add a mapping for each of those slots */ ++ /* Reuse the existing mapping if any */ + for (i = 0; i < count; ++i) { +- /* Reuse the existing mapping if any */ + for (j = 0; j < n_mappings; ++j) { + /* cppcheck-suppress nullPointer symbolName=mappings */ + /* false-positive: https://trac.cppcheck.net/ticket/9573 */ + if (mappings[j].funcs == funcs && +- mappings[j].real_slot == slots[i]) ++ mappings[j].real_slot == slots[i]) { ++ py->mappings[py->n_mappings].funcs = funcs; ++ py->mappings[py->n_mappings].real_slot = slots[i]; ++ py->mappings[py->n_mappings].wrap_slot = ++ mappings[j].wrap_slot; ++ ++py->n_mappings; + break; ++ } ++ } ++ if (n_mappings == 0 || j == n_mappings) { ++ new_slots[new_slots_count] = slots[i]; ++ ++new_slots_count; + } ++ } ++ ++ /* And now add a mapping for each new slot */ ++ for (i = 0; i < new_slots_count; ++i) { ++ ++py->last_id; + py->mappings[py->n_mappings].funcs = funcs; + py->mappings[py->n_mappings].wrap_slot = +- (n_mappings == 0 || j == n_mappings) ? +- py->n_mappings + MAPPING_OFFSET : +- mappings[j].wrap_slot; +- py->mappings[py->n_mappings].real_slot = slots[i]; ++ py->last_id + MAPPING_OFFSET; ++ py->mappings[py->n_mappings].real_slot = new_slots[i]; + ++py->n_mappings; + } ++ ++ free(new_slots); + } + + free (slots); +@@ -320,6 +337,7 @@ proxy_create (Proxy **res, CK_FUNCTION_LIST **loaded, + return_val_if_fail (py != NULL, CKR_HOST_MEMORY); + + py->forkid = p11_forkid; ++ py->last_id = 0; + + py->inited = modules_dup (loaded); + if (py->inited == NULL) { +-- +1.8.3.1 + diff --git a/p11-kit.spec b/p11-kit.spec index ae572f8..ad47865 100644 --- a/p11-kit.spec +++ b/p11-kit.spec @@ -1,6 +1,6 @@ Name: p11-kit Version: 0.23.20 -Release: 1 +Release: 2 Summary: Provides a way to load and enumerate PKCS#11 modules. License: BSD URL: http://p11-glue.freedesktop.org/p11-kit.html @@ -8,6 +8,12 @@ URL: http://p11-glue.freedesktop.org/p11-kit.html Source0: https://github.com/p11-glue/p11-kit/releases/download/%{version}/%{name}-%{version}.tar.xz Source1: p11-kit-client.service +Patch0: backport-CVE-2020-29363-Check-attribute-length-against-buffer-size.patch +Patch1: backport-CVE-2020-29362-Fix-bounds-check-in-p11_rpc_buffer_get_byte_array.patch +Patch2: backport-proxy-Fix-slot-ID-reuse-avoiding-duplicating-IDs.patch +Patch3: backport-0001-CVE-2020-29361-Check-for-arithmetic-overflows-before-allocating.patch +Patch4: backport-0002-CVE-2020-29361-Follow-up-to-arithmetic-overflow-fix.patch + BuildRequires: gcc libtasn1-devel >= 2.3 libffi-devel gtk-doc systemd-devel pkgconfig(glib-2.0) libxslt BuildRequires: bash-completion Provides: p11-kit-server = %{version}-%{release} @@ -121,6 +127,9 @@ fi %{_datadir}/bash-completion/completions/trust %changelog +* Sat Jan 9 2021 zoulin - 0.23.20-2 +- fix CVE-2020-29361 CVE-2020-29362 CVE-2020-29363 + * Mon Jul 27 2020 Liquor - 0.23.20-1 - update to 0.23.20 -- Gitee