Skip to content

Commit 105b64c

Browse files
committed
Merge tag 'for-linus-iommufd' of git://git.kernel.org/pub/scm/linux/kernel/git/jgg/iommufd
Pull iommufd fixes from Jason Gunthorpe: - An invalid VA range can be be put in a pages and eventually trigger WARN_ON, reject it early - Use of the wrong start index value when doing the complex batch carry scheme - Wrong store ordering resulting in corrupting data used in a later calculation that corrupted the batch structure during carry * tag 'for-linus-iommufd' of git://git.kernel.org/pub/scm/linux/kernel/git/jgg/iommufd: iommufd: Do not corrupt the pfn list when doing batch carry iommufd: Fix unpinning of pages when an access is present iommufd: Check for uptr overflow
2 parents ae52f79 + 13a0d1a commit 105b64c

File tree

1 file changed

+14
-2
lines changed

1 file changed

+14
-2
lines changed

drivers/iommu/iommufd/pages.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,9 +294,9 @@ static void batch_clear_carry(struct pfn_batch *batch, unsigned int keep_pfns)
294294
batch->npfns[batch->end - 1] < keep_pfns);
295295

296296
batch->total_pfns = keep_pfns;
297-
batch->npfns[0] = keep_pfns;
298297
batch->pfns[0] = batch->pfns[batch->end - 1] +
299298
(batch->npfns[batch->end - 1] - keep_pfns);
299+
batch->npfns[0] = keep_pfns;
300300
batch->end = 0;
301301
}
302302

@@ -1142,6 +1142,7 @@ struct iopt_pages *iopt_alloc_pages(void __user *uptr, unsigned long length,
11421142
bool writable)
11431143
{
11441144
struct iopt_pages *pages;
1145+
unsigned long end;
11451146

11461147
/*
11471148
* The iommu API uses size_t as the length, and protect the DIV_ROUND_UP
@@ -1150,6 +1151,9 @@ struct iopt_pages *iopt_alloc_pages(void __user *uptr, unsigned long length,
11501151
if (length > SIZE_MAX - PAGE_SIZE || length == 0)
11511152
return ERR_PTR(-EINVAL);
11521153

1154+
if (check_add_overflow((unsigned long)uptr, length, &end))
1155+
return ERR_PTR(-EOVERFLOW);
1156+
11531157
pages = kzalloc(sizeof(*pages), GFP_KERNEL_ACCOUNT);
11541158
if (!pages)
11551159
return ERR_PTR(-ENOMEM);
@@ -1203,13 +1207,21 @@ iopt_area_unpin_domain(struct pfn_batch *batch, struct iopt_area *area,
12031207
unsigned long start =
12041208
max(start_index, *unmapped_end_index);
12051209

1210+
if (IS_ENABLED(CONFIG_IOMMUFD_TEST) &&
1211+
batch->total_pfns)
1212+
WARN_ON(*unmapped_end_index -
1213+
batch->total_pfns !=
1214+
start_index);
12061215
batch_from_domain(batch, domain, area, start,
12071216
last_index);
1208-
batch_last_index = start + batch->total_pfns - 1;
1217+
batch_last_index = start_index + batch->total_pfns - 1;
12091218
} else {
12101219
batch_last_index = last_index;
12111220
}
12121221

1222+
if (IS_ENABLED(CONFIG_IOMMUFD_TEST))
1223+
WARN_ON(batch_last_index > real_last_index);
1224+
12131225
/*
12141226
* unmaps must always 'cut' at a place where the pfns are not
12151227
* contiguous to pair with the maps that always install

0 commit comments

Comments
 (0)