On Tue, Oct 25, 2022 at 03:12:18PM -0300, Jason Gunthorpe wrote:
+static int iopt_check_iova(struct io_pagetable *iopt, unsigned long iova,
unsigned long length)
+{
- unsigned long last;
- lockdep_assert_held(&iopt->iova_rwsem);
- if ((iova & (iopt->iova_alignment - 1)) ||
(length & (iopt->iova_alignment - 1)) || !length)
return -EINVAL;
syzkaller noticed this length check is too late, if userpsace supplies an invalid length and asks for automatic IOVA allocation it will trigger a WARN_ON.
@@ -177,8 +177,7 @@ static int iopt_check_iova(struct io_pagetable *iopt, unsigned long iova,
lockdep_assert_held(&iopt->iova_rwsem);
- if ((iova & (iopt->iova_alignment - 1)) || - (length & (iopt->iova_alignment - 1)) || !length) + if ((iova & (iopt->iova_alignment - 1))) return -EINVAL;
if (check_add_overflow(iova, length - 1, &last)) @@ -248,6 +247,11 @@ static int iopt_alloc_area_pages(struct io_pagetable *iopt, }
down_write(&iopt->iova_rwsem); + if ((length & (iopt->iova_alignment - 1)) || !length) { + rc = -EINVAL; + goto out_unlock; + } + if (flags & IOPT_ALLOC_IOVA) { /* Use the first entry to guess the ideal IOVA alignment */ elm = list_first_entry(pages_list, struct iopt_pages_list,
And a test to cover it
Jason