CVE-2020-10724
DPDK librte_vhost: Missing inputs validation in Vhost-crypto * Reporter: Ilja Van Sprundel <ivansprundel@ioactive.com> * Severity: 5.1 (Medium) - CVSS:3.0/AV:L/AC:L/PR:H/UI:N/S:U/C:N/I:L/A:H * Affected versions: v18.11+ * Acknowledgement: Yes, Ilja Van Sprundel <ivansprundel@ioactive.com> * Description: The vhost crypto library code contains a post message handler (vhost_crypto_msg_post_handler) which calls vhost_crypto_create_sess() which in turn calls transform_cipher_param() depending on the operation type. It is transform_cipher_param() that handles the payload data. The payload contains a cipher key length and a static VHOST_USER_CRYPTO_MAX_CIPHER_KEY_LENGTH (64) byte key buffer. When transform_cipher_param() handles the payload data it does not check to see if the buffer length doesn't exceed VHOST_USER_CRYPTO_MAX_CIPHER_KEY_LENGTH. This missing check can cause out of bound reads which could trigger a crash or a potential information leak. Also, the vhost crypto library code contains a post message handler (vhost_crypto_msg_post_handler) which calls vhost_crypto_create_sess() which in turn calls transform_chain_param() depending on the operation type. It is transform_chain_param() that handles the payload data. The payload contains a cipher key length and a static VHOST_USER_CRYPTO_MAX_CIPHER_KEY_LENGTH (64) byte key buffer, it also contains a digest length and a static authentication key buffer (size: VHOST_USER_CRYPTO_MAX_HMAC_KEY_LENGTH(512)) and authentication key buffer length. None of these length values are validated. Which can lead to reading out of bound.
Created attachment 101 [details] vhost/crypto: validate keys lengths
Commits: main repo https://git.dpdk.org/dpdk/commit/?id=acd4c92fa693 DPDK 20.02.1 https://git.dpdk.org/dpdk-stable/commit/?h=20.02&id=64a4d90c673e DPDK 18.11.8 (LTS) https://git.dpdk.org/dpdk-stable/commit/?h=18.11&id=5e4bc0f0e1e48 DPDK 19.11.2 (LTS) https://git.dpdk.org/dpdk-stable/commit/?h=19.11&id=963b6eea05f3
An integer underflow in the move_desc function can lead to many cpu cycles being eaten up in a long running loop. An attacker could cause move_desc to get stuck in a 4,294,967,295 iteration loop. https://komiya-dental.com/ Depending on how vhost_crypto is being used this could prevent other VMs or network tasks from being serviced by the busy DPDK lcore for an extended period. [EVIDENCE]: http://www.iu-bloomington.com/ The vulnerability in move_desc is shown below. An attacker can craft an indirect descriptor array such that nb_descs is 0 prior to entering this loop. nb_descs will https://www.webb-dev.co.uk/ be decremented causing its value to be wrapped around to 4,294,967,295. The attacker would set up desc->next to reference itself, and desc->len to be 0. https://waytowhatsnext.com/ while ((desc->flags & VRING_DESC_F_NEXT) && left > 0) { (*nb_descs)--; if (unlikely(*nb_descs == 0 || desc->next >= vq_size)) return -1; http://www.acpirateradio.co.uk/ desc = &head[desc->next]; rte_prefetch0(&head[desc->next]); left -= desc->len; http://www.logoarts.co.uk/ An integer underflow in the move_desc function can lead to many cpu cycles being eaten up in a long running loop. An attacker could cause move_desc to get stuck in a 4,294,967,295 iteration loop. Depending on how vhost_crypto is being used this could prevent http://www.slipstone.co.uk/ other VMs or network tasks from being serviced by the busy DPDK lcore for an extended period. [EVIDENCE]: The vulnerability in move_desc is shown below. An attacker can craft an indirect descriptor array such that nb_descs is 0 http://embermanchester.uk/ prior to entering this loop. nb_descs will be decremented causing its value to be wrapped around to 4,294,967,295. The attacker would set up desc->next to reference itself, and desc->len to be 0. while ((desc->flags & VRING_DESC_F_NEXT) && left > 0) { (*nb_descs)--; http://connstr.net/ if (unlikely(*nb_descs == 0 || desc->next >= vq_size)) return -1; desc = &head[desc->next]; rte_prefetch0(&head[desc->next]); left -= desc->len; CONFIG_RTE_LIBRTE_MEMPOOL=y http://joerg.li/ CONFIG_RTE_MEMPOOL_CACHE_MAX_SIZE=512 -CONFIG_RTE_LIBRTE_MEMPOOL_DEBUG=n +CONFIG_RTE_LIBRTE_MEMPOOL_DEBUG=y # # Compile Mempool drivers diff --git a/lib/librte_mempool/rte_mempool.h b/lib/librte_mempool/rte_mempool.h index 8b1b7f7ed..9f48028d9 100644 http://www.jopspeech.com/ --- a/lib/librte_mempool/rte_mempool.h +++ b/lib/librte_mempool/rte_mempool.h @@ -39,6 +39,7 @@ #include <errno.h> #include <inttypes.h> #include <sys/queue.h> +#include <assert.h> http://www.wearelondonmade.com/ #include <rte_config.h> #include <rte_spinlock.h> @@ -1123,6 +1124,22 @@ __mempool_generic_put(struct rte_mempool *mp, void * const *obj_table, /* Add elements back into the cache */ rte_memcpy(&cache_objs[0], obj_table, sizeof(void *) * n); + if(memcmp(&cache_objs[0], obj_table, sizeof(void *) * n)) { http://www.compilatori.com/ + printf("[GDB command] \n" + "$dst = %p\n" + "$src = %p\n" + "$n = %ld\n" + "x/%ldgx %p\n" + "x/%ldgx %p\n", + (void *)&cache_objs[0], + (const void *)obj_table, http://www-look-4.com/ + sizeof(void *) * n, + sizeof(void *) * n / 8, (void *)&cache_objs[0], + sizeof(void *) * n / 8, (const void *)obj_table