[PATCH v1 2/6] s390/vfio_ccw: limit the number of channel program segments

From: Eric Farman

Date: Tue Jul 14 2026 - 19:22:37 EST


The processing of channel programs, and the CCWs within them, is done
recursively. As such, there is an arbitrary (but not architectural)
limit to the number of CCWs that can exist in a single channel program.

The vfio-ccw logic breaks these channel programs into segments whenever
it encounters a Transfer-In-Channel (TIC) CCW, and the combined number
of segments count towards the global limit. Impose an equivalent limit
to the number of segments until such logic can be made non-recursive.

Fixes: 0a19e61e6d4c ("vfio: ccw: introduce channel program interfaces")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Eric Farman <farman@xxxxxxxxxxxxx>
---
drivers/s390/cio/vfio_ccw_cp.c | 5 +++++
drivers/s390/cio/vfio_ccw_cp.h | 6 ++++++
2 files changed, 11 insertions(+)

diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index 80c3d87f5482..76632b18fc37 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -319,6 +319,9 @@ static struct ccwchain *ccwchain_alloc(struct channel_program *cp, int len)
{
struct ccwchain *chain;

+ if (cp->ccwchain_count >= CCWCHAIN_COUNT_MAX)
+ return NULL;
+
chain = kzalloc_obj(*chain);
if (!chain)
return NULL;
@@ -332,6 +335,7 @@ static struct ccwchain *ccwchain_alloc(struct channel_program *cp, int len)
goto out_err;

list_add_tail(&chain->next, &cp->ccwchain_list);
+ cp->ccwchain_count++;

return chain;

@@ -731,6 +735,7 @@ int cp_init(struct channel_program *cp, union orb *orb)
vdev->dev,
"Prefetching channel program even though prefetch not specified in ORB");

+ cp->ccwchain_count = 0;
INIT_LIST_HEAD(&cp->ccwchain_list);
memcpy(&cp->orb, orb, sizeof(*orb));

diff --git a/drivers/s390/cio/vfio_ccw_cp.h b/drivers/s390/cio/vfio_ccw_cp.h
index fc31eb699807..dc91a317ef19 100644
--- a/drivers/s390/cio/vfio_ccw_cp.h
+++ b/drivers/s390/cio/vfio_ccw_cp.h
@@ -23,6 +23,11 @@
*/
#define CCWCHAIN_LEN_MAX 256

+/*
+ * Maximum number of chains
+ */
+#define CCWCHAIN_COUNT_MAX 16
+
/**
* struct channel_program - manage information for channel program
* @ccwchain_list: list head of ccwchains
@@ -38,6 +43,7 @@ struct channel_program {
union orb orb;
bool initialized;
struct ccw1 *guest_cp;
+ int ccwchain_count;
};

int cp_init(struct channel_program *cp, union orb *orb);
--
2.53.0