Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+14 -2
+14 -2
drivers/iommu/iommufd/pages.c
··· 294 294 batch->npfns[batch->end - 1] < keep_pfns); 295 295 296 296 batch->total_pfns = keep_pfns; 297 - batch->npfns[0] = keep_pfns; 298 297 batch->pfns[0] = batch->pfns[batch->end - 1] + 299 298 (batch->npfns[batch->end - 1] - keep_pfns); 299 + batch->npfns[0] = keep_pfns; 300 300 batch->end = 0; 301 301 } 302 302 ··· 1142 1142 bool writable) 1143 1143 { 1144 1144 struct iopt_pages *pages; 1145 + unsigned long end; 1145 1146 1146 1147 /* 1147 1148 * The iommu API uses size_t as the length, and protect the DIV_ROUND_UP ··· 1150 1149 */ 1151 1150 if (length > SIZE_MAX - PAGE_SIZE || length == 0) 1152 1151 return ERR_PTR(-EINVAL); 1152 + 1153 + if (check_add_overflow((unsigned long)uptr, length, &end)) 1154 + return ERR_PTR(-EOVERFLOW); 1153 1155 1154 1156 pages = kzalloc(sizeof(*pages), GFP_KERNEL_ACCOUNT); 1155 1157 if (!pages) ··· 1207 1203 unsigned long start = 1208 1204 max(start_index, *unmapped_end_index); 1209 1205 1206 + if (IS_ENABLED(CONFIG_IOMMUFD_TEST) && 1207 + batch->total_pfns) 1208 + WARN_ON(*unmapped_end_index - 1209 + batch->total_pfns != 1210 + start_index); 1210 1211 batch_from_domain(batch, domain, area, start, 1211 1212 last_index); 1212 - batch_last_index = start + batch->total_pfns - 1; 1213 + batch_last_index = start_index + batch->total_pfns - 1; 1213 1214 } else { 1214 1215 batch_last_index = last_index; 1215 1216 } 1217 + 1218 + if (IS_ENABLED(CONFIG_IOMMUFD_TEST)) 1219 + WARN_ON(batch_last_index > real_last_index); 1216 1220 1217 1221 /* 1218 1222 * unmaps must always 'cut' at a place where the pfns are not