diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c index 8d1b2771c1aa0252df0196e08189691a474c7066..05a76f973387f86604706c2293cd3ffbdb25610f 100644 --- a/drivers/s390/cio/vfio_ccw_cp.c +++ b/drivers/s390/cio/vfio_ccw_cp.c @@ -334,6 +334,7 @@ static struct ccwchain *ccwchain_alloc(struct channel_program *cp, int len) chain->ch_len = len; list_add_tail(&chain->next, &cp->ccwchain_list); + cp->ccwchain_count++; return chain; } @@ -441,6 +442,10 @@ static int ccwchain_handle_ccw(u32 cda, struct channel_program *cp) if (len < 0) return len; + /* Limit number of chains in a single channel program */ + if (cp->ccwchain_count >= CCWCHAIN_COUNT_MAX) + return -EINVAL; + /* Need alloc a new chain for this one. */ chain = ccwchain_alloc(cp, len); if (!chain) @@ -652,6 +657,7 @@ int cp_init(struct channel_program *cp, struct device *mdev, union orb *orb) if (!orb->cmd.pfch && __ratelimit(&ratelimit_state)) dev_warn(mdev, "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)); cp->mdev = mdev; diff --git a/drivers/s390/cio/vfio_ccw_cp.h b/drivers/s390/cio/vfio_ccw_cp.h index ba31240ce96594ef9e21c3fd1d5c731b791b6898..6ac5f0b945d7195b502a6e1a56193be5c2401f33 100644 --- a/drivers/s390/cio/vfio_ccw_cp.h +++ b/drivers/s390/cio/vfio_ccw_cp.h @@ -23,12 +23,19 @@ */ #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 * @orb: orb for the currently processed ssch request * @mdev: the mediated device to perform page pinning/unpinning * @initialized: whether this instance is actually initialized + * @guest_cp: copy of guest channel program + * @ccwchain_count: number of channel program segments (linked by TIC) * * @ccwchain_list is the head of a ccwchain list, that contents the * translated result of the guest channel program that pointed out by @@ -40,6 +47,7 @@ struct channel_program { struct device *mdev; bool initialized; struct ccw1 *guest_cp; + unsigned int ccwchain_count; }; extern int cp_init(struct channel_program *cp, struct device *mdev,