Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 214AE3D4131; Thu, 20 Aug 2026 15:25:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787239506; cv=none; b=t8LTohobjNhsj+mWU+Zmtk7UE5EPtSgT3nD5jE/3LgJblOicMbiPVfwVL7ogcxwO7p3cQlE/Jx4lzqp0+GbaJ0eN+lWHVQPExk2VpsfsWJFaNnl+8h/OudSPZvHL1veRf8DVygY3Kqid7hcs7uc5iFVNe49xVU9WBA7uHBJovO0= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787239506; c=relaxed/simple; bh=XFVGiPUaoYsG7rxoxZ5RjMxsF/m+dfOTA4NQ3BMj+qg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gE7/P1iB0/8eadgsNwZ5zg3Ne3O67a6GXPT3BAmVsm4I3auaS9d8B7mXZ3wyOSt2OWsZE9CjHPVR6qji7hKuIuAcSVCVEUeMUsE+XGt6EwrkUgN4ac7nkxyHPs2eSJVNofJcykBle4qWY8NzLfUXbz+SgHuOWtJazrCLYxtdWtE= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=0c823NCz; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="0c823NCz" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 42DA01F000E9; Thu, 20 Aug 2026 15:25:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1787239504; bh=FHIC6TIMEkfqZdT8TZsqu5Qn2WP2mPVeZVSK4Rx7lj8=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=0c823NCzG1GoB/qvKmc9dJkYdIYMeuJyl++tW8i3iqS7AnsqeYsG4K0+YA7h0cBBG SJzt1DL25LgWj+TyVcXE5oZtqO4gSzLEOS2sk9Lq21hARzzS5ktmGGKRg/nBGjyK+z 3u9HGQxNJt8QjuduDOBaPedLpWFIdcKYhrmEcIvs= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Cornelia Huck , Matthew Rosato , Eric Farman , Christian Borntraeger Subject: [PATCH 6.12 073/220] s390/vfio_ccw: Ensure index for read/write regions are within range Date: Thu, 20 Aug 2026 16:54:23 +0200 Message-ID: <20260820145225.683402649@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260820145223.480031205@linuxfoundation.org> References: <20260820145223.480031205@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 6.12-stable review patch. If anyone has any objections, please let me know. ------------------ From: Eric Farman commit 9f5f9a78fedc45bc29d6a0a64e3a3472361afae5 upstream. The introduction of the capability chain rightly clamped the region indexes to the range of the capabilities itself, but neglected to do so for the existing read/write regions which should also be enforced. Fixes: db8e5d17ac03 ("vfio-ccw: add capabilities chain") Cc: stable@vger.kernel.org Cc: Cornelia Huck Reviewed-by: Matthew Rosato Signed-off-by: Eric Farman Signed-off-by: Christian Borntraeger Signed-off-by: Greg Kroah-Hartman --- drivers/s390/cio/vfio_ccw_async.c | 16 ++++++++++++++++ drivers/s390/cio/vfio_ccw_chp.c | 15 +++++++++++++++ drivers/s390/cio/vfio_ccw_ops.c | 7 +++---- 3 files changed, 34 insertions(+), 4 deletions(-) --- a/drivers/s390/cio/vfio_ccw_async.c +++ b/drivers/s390/cio/vfio_ccw_async.c @@ -8,6 +8,7 @@ */ #include +#include #include "vfio_ccw_private.h" @@ -24,11 +25,20 @@ static ssize_t vfio_ccw_async_region_rea return -EINVAL; mutex_lock(&private->io_mutex); + + if (i >= private->num_regions) { + ret = -EINVAL; + goto out_unlock; + } + + i = array_index_nospec(i, private->num_regions); region = private->region[i].data; if (copy_to_user(buf, (void *)region + pos, count)) ret = -EFAULT; else ret = count; + +out_unlock: mutex_unlock(&private->io_mutex); return ret; } @@ -48,6 +58,12 @@ static ssize_t vfio_ccw_async_region_wri if (!mutex_trylock(&private->io_mutex)) return -EAGAIN; + if (i >= private->num_regions) { + ret = -EINVAL; + goto out_unlock; + } + + i = array_index_nospec(i, private->num_regions); region = private->region[i].data; if (copy_from_user((void *)region + pos, buf, count)) { ret = -EFAULT; --- a/drivers/s390/cio/vfio_ccw_chp.c +++ b/drivers/s390/cio/vfio_ccw_chp.c @@ -9,6 +9,7 @@ */ #include +#include #include #include "vfio_ccw_private.h" @@ -26,6 +27,13 @@ static ssize_t vfio_ccw_schib_region_rea return -EINVAL; mutex_lock(&private->io_mutex); + + if (i >= private->num_regions) { + ret = -EINVAL; + goto out; + } + + i = array_index_nospec(i, private->num_regions); region = private->region[i].data; if (cio_update_schib(sch)) { @@ -97,6 +105,12 @@ static ssize_t vfio_ccw_crw_region_read( list_del(&crw->next); mutex_lock(&private->io_mutex); + if (i >= private->num_regions) { + ret = -EINVAL; + goto out; + } + + i = array_index_nospec(i, private->num_regions); region = private->region[i].data; if (crw) @@ -109,6 +123,7 @@ static ssize_t vfio_ccw_crw_region_read( region->crw = 0; +out: mutex_unlock(&private->io_mutex); kfree(crw); --- a/drivers/s390/cio/vfio_ccw_ops.c +++ b/drivers/s390/cio/vfio_ccw_ops.c @@ -259,6 +259,7 @@ static ssize_t vfio_ccw_mdev_read(struct return vfio_ccw_mdev_read_io_region(private, buf, count, ppos); default: index -= VFIO_CCW_NUM_REGIONS; + index = array_index_nospec(index, private->num_regions); return private->region[index].ops->read(private, buf, count, ppos); } @@ -311,6 +312,7 @@ static ssize_t vfio_ccw_mdev_write(struc return vfio_ccw_mdev_write_io_region(private, buf, count, ppos); default: index -= VFIO_CCW_NUM_REGIONS; + index = array_index_nospec(index, private->num_regions); return private->region[index].ops->write(private, buf, count, ppos); } @@ -353,11 +355,8 @@ static int vfio_ccw_mdev_get_region_info VFIO_CCW_NUM_REGIONS + private->num_regions) return -EINVAL; - info->index = array_index_nospec(info->index, - VFIO_CCW_NUM_REGIONS + - private->num_regions); - i = info->index - VFIO_CCW_NUM_REGIONS; + i = array_index_nospec(i, private->num_regions); info->offset = VFIO_CCW_INDEX_TO_OFFSET(info->index); info->size = private->region[i].size;