From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f178.google.com (mail-pl1-f178.google.com [209.85.214.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6E46E3F7894 for ; Wed, 3 Jun 2026 18:39:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.178 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780511963; cv=none; b=oCtwv/apULblvjAhpQdlFpJQv1eKVmt/lsTTyeXJKIRpWQziuetVV6E6TFxNDyEQ9ocCkWmHefDzXIDFqvVd38O69W2BIF21ZL4Yz24z+fW1cWgFCjd+YG4lh9tjkPWKQ0jA89c4D7rsNhvXNHdZ03fKxJjz20Kq4VBF9oIoMUQ= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780511963; c=relaxed/simple; bh=TF4ItLZ8YlQvNhPtSMEpt7L6QIJyhDMz4eCFIc7jA2Q=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=skKDz/C4mJJUmR0GPqp8B7wDCxazLBqND/IRSzTx29HM2/Ij6GdIw8yrMsAE8gCbVJzx9HQqZiNxuiigXJVZ+C9pTgokiCXiK9XJ6t9jWNpvUv79pEqUL8S7HGzsxpBnR3CzoWy1R3rwS9FOC+mx9X4iClprkozY7RbpLP7yCys= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=C2aQqf7T; arc=none smtp.client-ip=209.85.214.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="C2aQqf7T" Received: by mail-pl1-f178.google.com with SMTP id d9443c01a7336-2bf18c30bb2so47155615ad.0 for ; Wed, 03 Jun 2026 11:39:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1780511960; x=1781116760; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ozUbJpWYUhzivTommeH38n12r1e/VD6cdi/cyCWnfZE=; b=C2aQqf7TsalDd4CW7Jb876kmNWw1IAYijTyJ4MElE8JrLQr0xej+k1gvFEjiKsqVoA QyQw2cLI4xqi3O7XubWKYlGY7TrqF58UWU/gMt6bsOiQbQPrJKf7PhSmwD8fPo8KCUTq PmyVZYKYIpjosQFD6U7bRcwgKIgwLfhM4rZK7NveQrK+9RH8owUEywVg+fDj+TgM2YLu ffYyIQobynO2jeUr7EiQGjxjQDiQPYu2IYq9ydeyLk/GTZFiQ7viSkU+AoH8vDC+hFfj Gi2bLgrf1Ma8yzoD+fP8HKv+ddLUfhh/NgPzG1YJGVZNASvuTBBVPzt2Mkf68A+WDRZ/ RkWQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780511960; x=1781116760; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=ozUbJpWYUhzivTommeH38n12r1e/VD6cdi/cyCWnfZE=; b=nmlUa6m+K47FHRHAKWQlpVKRBVI4zclNVgaqKCB9UTl7aMclASl2johiwFmmGTYfEZ umyB8kHr1xlrDoNwHoQ1Mg4DPjdIF6AhVK4nisNGU3V+gpXjphNgR9sj8D+Y/fcvJQ5m UEg+LSG7+fmkuIT7FAQITJ6cgDwZXppwuSE2cP/pE6xXhk7tjnt19LBv+pEn0VRhT3F7 3jIcWxXSkfJEXU+NaY6OsSpGBZV1wzHLAgfSWE9HTPaokfAYdiAzfdwIBS76ItNpHisr oS5I2swBpXUl9NEdbFxjkY9ZqaY//mB8/lMOjassy+9S4aKCmDQ0Z4YB3FoiWbijqucr tmUw== X-Forwarded-Encrypted: i=1; AFNElJ+X7UCIb491RyHjzEyzaJR8Tb7EzJEktKoCyarJUVlJymgRnIk7o53q3yArvxl0I9THpxIQFWqY75fZhBM=@vger.kernel.org X-Gm-Message-State: AOJu0YwWCXNyHkD2mycXJ1UO0pHw6xJr5cVSdLuAhxBQEJGzyKW3FHpk YCCwaOyYXiloDxLYZyhkueEiXpYMe7izFWNkQDR1SRGRpm53J+krBNuC X-Gm-Gg: Acq92OGvtfT8UPfehKW4bZYCkVZM56/12g9DTwgcyBg+VPcUW08anUe5ysS+XLLJzQx cadmgba2jFQy7CjSEF0kPxfXxWjLTCsZcfh8tsYA/xB+opyNvQsfAdIsg9HXc6unnlCnE3CH8+z zSZU5WQxJJL9vuoocvIqBUrRyMaeILRv/ZBF26sRlKFNGOlD2w3WAnnd8KtreBikktxsx3SGRe/ +ZLzDmRaJqxmmCOCwvmIQ7A+N9V9kAHNs/tN/5zmsUoTzBNnxwiuWbTgtCc6ddIM9dtjhjONHBw dFtVXViUKCkqlEzjVbtMvMllWg9K1UTJ5Kc/I0ZayGSVmdP7HR2pBpe1q06cCKMHp9ANR6lL9nH LrGDzISbYvyhb6ecAEddzdV8N3BDEz/YyvLpbkqXBgvP2BZWQ84WtvY6g6HAR5Af8cWGn+SmulL ss2IvsWIRN0e0XdAUaT/A58zxrzzvQ/CGCfj6Nkxd/XQZAuSVC6bTgfCXnc45EE6OfJd7dCO7vK mxv1XLdwPs1DPly46zgiCDI8nu5cWK586hFnQ== X-Received: by 2002:a17:902:c602:b0:2c0:a555:80d6 with SMTP id d9443c01a7336-2c163a14eb7mr29911955ad.2.1780511960422; Wed, 03 Jun 2026 11:39:20 -0700 (PDT) Received: from baver-zenith.localdomain ([124.49.88.131]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2c16649c01asm32764915ad.74.2026.06.03.11.39.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Jun 2026 11:39:19 -0700 (PDT) From: Sungho Bae To: amit@kernel.org, arnd@arndb.de, gregkh@linuxfoundation.org Cc: virtualization@lists.linux.dev, linux-kernel@vger.kernel.org, Sungho Bae Subject: [PATCH v3 3/4] virtio_console: fix control queue race during restore Date: Thu, 4 Jun 2026 03:37:56 +0900 Message-Id: <20260603183757.21587-4-baver.bae@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260603183757.21587-1-baver.bae@gmail.com> References: <20260603183757.21587-1-baver.bae@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Sungho Bae In virtcons_restore(), after virtio_device_ready() sets DRIVER_OK, the device becomes active. If the control receive queue (c_ivq) is populated immediately, the host can instantly deliver pending control messages (e.g., VIRTIO_CONSOLE_PORT_REMOVE). This triggers the control_work_handler(), which can modify the portdev->ports list concurrently with the unprotected list_for_each_entry loop in virtcons_restore(), leading to list corruption or Use-After-Free. Fix this by deferring the population of the control receive queue (fill_queue for c_ivq) until after the list iteration is complete. This ensures the host cannot inject control messages during the vulnerable window. Signed-off-by: Sungho Bae --- drivers/char/virtio_console.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 589a12261e23..dd31f7069e19 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -2164,9 +2164,6 @@ static int virtcons_restore(struct virtio_device *vdev) virtio_device_ready(portdev->vdev); - if (use_multiport(portdev)) - fill_queue(portdev->c_ivq, &portdev->c_ivq_lock); - list_for_each_entry(port, &portdev->ports, list) { port->in_vq = portdev->in_vqs[port->id]; port->out_vq = portdev->out_vqs[port->id]; @@ -2183,6 +2180,18 @@ static int virtcons_restore(struct virtio_device *vdev) if (port->guest_connected) send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 1); } + + /* + * Populate the control receive queue only after the list iteration + * is complete. If we fill this queue before iterating, the host could + * immediately deliver a VIRTIO_CONSOLE_PORT_REMOVE message. + * This would trigger the control workqueue, which modifies the + * portdev->ports list concurrently with the unprotected loop above, + * leading to a Use-After-Free and list corruption. + */ + if (use_multiport(portdev)) + fill_queue(portdev->c_ivq, &portdev->c_ivq_lock); + return 0; } #endif -- 2.34.1