Bug 724 - Guest causes DPDK to read out of bounds
Summary: Guest causes DPDK to read out of bounds
Status: UNCONFIRMED
Alias: None
Product: DPDK
Classification: Unclassified
Component: vhost/virtio (show other bugs)
Version: 20.11
Hardware: All All
: Normal normal
Target Milestone: ---
Assignee: dev
URL:
Depends on:
Blocks:
 
Reported: 2021-06-01 13:17 CEST by Cheng Jiang
Modified: 2021-06-01 14:16 CEST (History)
1 user (show)



Attachments

Description Cheng Jiang 2021-06-01 13:17:20 CEST
Report From: dsfasd daf <coolboy43433@gmail.com>
Report Date: Thu, 11 Mar 2021 10:24:24 +0000

Report:


Hi, 
I am clark, a security researcher of Tencent Blade Team. I recently discovered several security vulnerabilities in DPDK, as follows

1. 
Code:
	examples/vhost/virtio_net.c 
		vs_enqueue_pkts()
			desc_indexes[i] = vr->avail->ring[used_idx];
			...
			uint16_t desc_idx = desc_indexes[i];
			err = enqueue_pkt(dev, vr, pkts[i], desc_idx);
		
		enqueue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr, struct rte_mbuf *m, uint16_t desc_idx) {
			...
			desc = &vr->desc[desc_idx];
		}
description:
	desc_indexes[i] = vr->avail->ring[used_idx] Its value can be fully controlled by the guest, which will cause out-of-bounds writing in the enqueue_pkt function
harm:
	Guest causes DPDK to write out of bounds
patch suggestions:
	vs_enqueue_pkts() {
		...
	+	if (vr->avail->ring[used_idx] >= vr->size)
	+		return 0;
		desc_indexes[i] = vr->avail->ring[used_idx];
		...
	}

2. 
Code:
	examples/vhost/virtio_net.c 
		vs_dequeue_pkts()
			desc_indexes[i] = vr->avail->ring[avail_idx];
			dequeue_pkt(dev, vr, pkts[i], desc_indexes[i], mbuf_pool);
		dequeue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr, struct rte_mbuf *m, uint16_t desc_idx, struct rte_mempool *mbuf_pool) {
			desc = &vr->desc[desc_idx];
		}
description:
	desc_indexes[i] = vr->avail->ring[avail_idx]; Its value can be fully controlled by the guest, which will cause out-of-bounds reading in the dequeue_pkt function.
harm:
	Guest causes DPDK to read out of bounds
patch suggestions:
	vs_dequeue_pkts() {
		...
	+	if (vr->avail->ring[used_idx] >= vr->size)
	+		return 0;
		desc_indexes[i] = vr->avail->ring[avail_idx];
		...
	}

3. 
Code:
	examples/vhost_blk/vhost_blk.c
		vq_get_desc_idx()
			desc_idx = vq->vring.avail->ring[last_avail_idx];
		process_vq()
			desc_idx = vq_get_desc_idx(vq);
			task = &vq->tasks[desc_idx];
			...
			process_blk_task(task);
description:
	desc_idx = vq->vring.avail->ring[last_avail_idx]; Its value can be fully controlled by the guest, process_blk_task(task); will further cause out-of-bounds read and write.
harm:
	Guest causes DPDK to read and write out of bounds
patch suggestions:
	process_vq() {
		desc_idx = vq_get_desc_idx(vq);
	+	if (desc_idx >= vq->vring.size)
			return;
		task = &vq->tasks[desc_idx];

	
4. 
Code:
	lib/librte_vhost/vhost_user.c  
		vhost_user_postcopy_register() 
			if (read_vhost_message(main_fd, &ack_msg) <= 0) {}
description:
	vhost_user_postcopy_register is called in the vhost_user_set_mem_table function, When dev->postcopy_listening was set to 1, vhost_user_postcopy_register will call read_vhost_message 
and wait for qemu to respond to this message. If there is a Malicious qemu process does not reply to this message, DPDK will wait for the response indefinitely, and other legitimate qemu processes 
will not be able to communicate with DPDK normally. This will result in A DoS attack.
harm:
	qemu causes DPDK denial of service
patch suggestions:
	Add a timeout mechanism

5. 
Code:
	lib/librte_vhost/vhost_crypto.c
		rte_vhost_crypto_fetch_requests()
			uint16_t desc_idx = vq->avail->ring[used_idx];
			struct vring_desc *head = &vq->desc[desc_idx];
			if (unlikely(vhost_crypto_process_one_req(vcrypto, vq,
					op, head, descs, used_idx) < 0))
description:
	uint16_t desc_idx = vq->avail->ring[used_idx]; Its value can be fully controlled by the guest, vhost_crypto_process_one_req(task); will further cause out-of-bounds reading.
harm:
	Guest causes DPDK to read out of bounds
patch suggestions:
	rte_vhost_crypto_fetch_requests()
		uint16_t desc_idx = vq->avail->ring[used_idx];
	+	if (desc_idx >= vq->size)
	+		return0;
		struct vring_desc *head = &vq->desc[desc_idx];

summary:
Vulnerability 1: The guest causes DPDK to write out of bounds, or it can cause the virtual machine to escape
Vulnerability 2: Guest causes DPDK to read out of bounds, or causes DPDK DoS
Vulnerability 3: The guest causes DPDK to read and write out of bounds, or it can cause the virtual machine to escape
Vulnerability 4: qemu causes DPDK denial of service
Vulnerability 5: guest causes DPDK to read out of bounds, or causes DPDK DoS
The above vulnerabilities 1, 2, and 3 are in the exampleCode, but I think it is still a serious threat, because these example codes may be used in formal occasions.
Comment 1 Ferruh YIGIT 2021-06-01 14:16:42 CEST
Just for some clarification on the defect, since it mentions security issues.

The original defect was created as a security defect, and after evaluation, it is decided to address issues as regular defects. The current defect is the copy/paste of the original report, that is why it talks about security issues.

Note You need to log in before you can comment on or make changes to this bug.