Along the line with observations in the context of XSA-448, besides "op" no field is relevant when the range to be flushed is empty, much like e.g. the pointers passed to memcpy() are irrelevant (and would never be "validated") when the passed length is zero. Split the existing condition validating "op", "offset", and "length", leaving only the "op" part ahead of the check for length being zero (or no flushing to be performed).
In the course of splitting also simplify the moved part of the condition from 3 to 2 conditionals, potentially (depending on the architecture) requiring one less (conditional) branch. Signed-off-by: Jan Beulich <[email protected]> --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -3528,15 +3528,16 @@ static int _cache_flush(const gnttab_cac void *v; int ret; - if ( (cflush->offset >= PAGE_SIZE) || - (cflush->length > PAGE_SIZE) || - (cflush->offset + cflush->length > PAGE_SIZE) || - (cflush->op & ~(GNTTAB_CACHE_INVAL | GNTTAB_CACHE_CLEAN)) ) + if ( cflush->op & ~(GNTTAB_CACHE_INVAL | GNTTAB_CACHE_CLEAN) ) return -EINVAL; if ( cflush->length == 0 || cflush->op == 0 ) return !*cur_ref ? 0 : -EILSEQ; + if ( (cflush->offset | cflush->length) > PAGE_SIZE || + cflush->offset + cflush->length > PAGE_SIZE ) + return -EINVAL; + /* currently unimplemented */ if ( cflush->op & GNTTAB_CACHE_SOURCE_GREF ) return -EOPNOTSUPP;
