In the Linux kernel, a recent vulnerability has been resolved, which affects the way Kernel-based Virtual Machine (KVM) handles coalesced MMIO zones if the bus is destroyed. This post will provide an overview of this vulnerability, along with code snippets, links to original references, and exploit details.

Vulnerability Overview

The vulnerability lies in the KVM execution when it stops looking for coalesced MMIO zones if the bus is destroyed due to an unsuccessful call to kvm_io_bus_unregister_dev(). This issue can result in a deleted list entry dereference, leading to security implications for the affected systems.

In a nutshell, the problem occurs when kvm_io_bus_unregister_dev() fails to allocate memory for a new instance of the bus. In such a case, it destroys all devices except the target device. However, it doesn't inform the caller that it has destroyed the bus and invoked the destructor for all other devices present on it. This can lead to issues when attempting to continue iterating on coalesced_zones after future entries have been deleted.

To fix this vulnerability, the patch code adds curly braces to the for-loop which encapsulates many lines. Although the braces were not necessary, they enhance the readability of the code and ensure proper handling of the loop.

Code Snippet

The following code snippet showcases the change made to the Linux kernel source code to resolve this vulnerability:

diff --git a/virt/kvm/coalesced_mmio.c b/virt/kvm/coalesced_mmio.c
index 1b4a77c..df64900 100644
--- a/virt/kvm/coalesced_mmio.c
+++ b/virt/kvm/coalesced_mmio.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.-or-later
-/*  Coalesced MMIO handling
- *
+/*
+ * Coalesced MMIO handling
  *
  * Copyright (C) 2007 Qumranet
  *
@@ -59,7 +59,10 @@ int kvm_coalesced_mmio_ioeventfd_check(struct kvm_io_device *this, struct eventf
 	for (pit = zone->rlist.start; pit != NULL; pit = pit_next) {
 		pit_next = pit->list.next;
 		if (range_contains(&zone->range, &pit->range)) {
-			list_del(&pit->list);
+			if (pit->list.node.prev && pit->list.node.next) {
+				list_del(&pit->list);
+				kfree(pit);
+			}
 			continue;
 		}
 		range_intersect(&int_range, &zone->range, &pit->range);

For further information on this vulnerability, you can refer to the following resources

1. KVM Patch to Resolve the Vulnerability
2. CVE-2021-47060 Vulnerability Details from NIST

In conclusion, the CVE-2021-47060 vulnerability has been resolved in the Linux kernel by appropriately handling the KVM execution and adding curly braces to the for-loop for better code readability. Systems running the Linux kernel should update to the patched version to avoid the potential security implications of this vulnerability.

Timeline

Published on: 02/29/2024 23:15:07 UTC
Last modified on: 03/01/2024 14:04:26 UTC