3838#include <linux/workqueue.h>
3939#include <linux/notifier.h>
4040#include <linux/mm_inline.h>
41+ #include <linux/overflow.h>
4142#include "vfio.h"
4243
4344#define DRIVER_VERSION "0.2"
@@ -182,7 +183,7 @@ static struct vfio_dma *vfio_find_dma(struct vfio_iommu *iommu,
182183}
183184
184185static struct rb_node * vfio_find_dma_first_node (struct vfio_iommu * iommu ,
185- dma_addr_t start , u64 size )
186+ dma_addr_t start , size_t size )
186187{
187188 struct rb_node * res = NULL ;
188189 struct rb_node * node = iommu -> dma_list .rb_node ;
@@ -895,14 +896,20 @@ static int vfio_iommu_type1_pin_pages(void *iommu_data,
895896 unsigned long remote_vaddr ;
896897 struct vfio_dma * dma ;
897898 bool do_accounting ;
899+ dma_addr_t iova_end ;
900+ size_t iova_size ;
898901
899- if (!iommu || !pages )
902+ if (!iommu || !pages || npage <= 0 )
900903 return - EINVAL ;
901904
902905 /* Supported for v2 version only */
903906 if (!iommu -> v2 )
904907 return - EACCES ;
905908
909+ if (check_mul_overflow (npage , PAGE_SIZE , & iova_size ) ||
910+ check_add_overflow (user_iova , iova_size - 1 , & iova_end ))
911+ return - EOVERFLOW ;
912+
906913 mutex_lock (& iommu -> lock );
907914
908915 if (WARN_ONCE (iommu -> vaddr_invalid_count ,
@@ -1008,12 +1015,21 @@ static void vfio_iommu_type1_unpin_pages(void *iommu_data,
10081015{
10091016 struct vfio_iommu * iommu = iommu_data ;
10101017 bool do_accounting ;
1018+ dma_addr_t iova_end ;
1019+ size_t iova_size ;
10111020 int i ;
10121021
10131022 /* Supported for v2 version only */
10141023 if (WARN_ON (!iommu -> v2 ))
10151024 return ;
10161025
1026+ if (WARN_ON (npage <= 0 ))
1027+ return ;
1028+
1029+ if (WARN_ON (check_mul_overflow (npage , PAGE_SIZE , & iova_size ) ||
1030+ check_add_overflow (user_iova , iova_size - 1 , & iova_end )))
1031+ return ;
1032+
10171033 mutex_lock (& iommu -> lock );
10181034
10191035 do_accounting = list_empty (& iommu -> domain_list );
@@ -1374,7 +1390,8 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
13741390 int ret = - EINVAL , retries = 0 ;
13751391 unsigned long pgshift ;
13761392 dma_addr_t iova = unmap -> iova ;
1377- u64 size = unmap -> size ;
1393+ dma_addr_t iova_end ;
1394+ size_t size = unmap -> size ;
13781395 bool unmap_all = unmap -> flags & VFIO_DMA_UNMAP_FLAG_ALL ;
13791396 bool invalidate_vaddr = unmap -> flags & VFIO_DMA_UNMAP_FLAG_VADDR ;
13801397 struct rb_node * n , * first_n ;
@@ -1387,6 +1404,11 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
13871404 goto unlock ;
13881405 }
13891406
1407+ if (iova != unmap -> iova || size != unmap -> size ) {
1408+ ret = - EOVERFLOW ;
1409+ goto unlock ;
1410+ }
1411+
13901412 pgshift = __ffs (iommu -> pgsize_bitmap );
13911413 pgsize = (size_t )1 << pgshift ;
13921414
@@ -1396,10 +1418,15 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
13961418 if (unmap_all ) {
13971419 if (iova || size )
13981420 goto unlock ;
1399- size = U64_MAX ;
1400- } else if (!size || size & (pgsize - 1 ) ||
1401- iova + size - 1 < iova || size > SIZE_MAX ) {
1402- goto unlock ;
1421+ size = SIZE_MAX ;
1422+ } else {
1423+ if (!size || size & (pgsize - 1 ))
1424+ goto unlock ;
1425+
1426+ if (check_add_overflow (iova , size - 1 , & iova_end )) {
1427+ ret = - EOVERFLOW ;
1428+ goto unlock ;
1429+ }
14031430 }
14041431
14051432 /* When dirty tracking is enabled, allow only min supported pgsize */
@@ -1446,7 +1473,7 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
14461473 if (dma && dma -> iova != iova )
14471474 goto unlock ;
14481475
1449- dma = vfio_find_dma (iommu , iova + size - 1 , 0 );
1476+ dma = vfio_find_dma (iommu , iova_end , 0 );
14501477 if (dma && dma -> iova + dma -> size != iova + size )
14511478 goto unlock ;
14521479 }
@@ -1648,16 +1675,25 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
16481675{
16491676 bool set_vaddr = map -> flags & VFIO_DMA_MAP_FLAG_VADDR ;
16501677 dma_addr_t iova = map -> iova ;
1678+ dma_addr_t iova_end ;
16511679 unsigned long vaddr = map -> vaddr ;
1680+ unsigned long vaddr_end ;
16521681 size_t size = map -> size ;
16531682 int ret = 0 , prot = 0 ;
16541683 size_t pgsize ;
16551684 struct vfio_dma * dma ;
16561685
16571686 /* Verify that none of our __u64 fields overflow */
16581687 if (map -> size != size || map -> vaddr != vaddr || map -> iova != iova )
1688+ return - EOVERFLOW ;
1689+
1690+ if (!size )
16591691 return - EINVAL ;
16601692
1693+ if (check_add_overflow (iova , size - 1 , & iova_end ) ||
1694+ check_add_overflow (vaddr , size - 1 , & vaddr_end ))
1695+ return - EOVERFLOW ;
1696+
16611697 /* READ/WRITE from device perspective */
16621698 if (map -> flags & VFIO_DMA_MAP_FLAG_WRITE )
16631699 prot |= IOMMU_WRITE ;
@@ -1673,13 +1709,7 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
16731709
16741710 WARN_ON ((pgsize - 1 ) & PAGE_MASK );
16751711
1676- if (!size || (size | iova | vaddr ) & (pgsize - 1 )) {
1677- ret = - EINVAL ;
1678- goto out_unlock ;
1679- }
1680-
1681- /* Don't allow IOVA or virtual address wrap */
1682- if (iova + size - 1 < iova || vaddr + size - 1 < vaddr ) {
1712+ if ((size | iova | vaddr ) & (pgsize - 1 )) {
16831713 ret = - EINVAL ;
16841714 goto out_unlock ;
16851715 }
@@ -1710,7 +1740,7 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
17101740 goto out_unlock ;
17111741 }
17121742
1713- if (!vfio_iommu_iova_dma_valid (iommu , iova , iova + size - 1 )) {
1743+ if (!vfio_iommu_iova_dma_valid (iommu , iova , iova_end )) {
17141744 ret = - EINVAL ;
17151745 goto out_unlock ;
17161746 }
@@ -2977,7 +3007,8 @@ static int vfio_iommu_type1_dirty_pages(struct vfio_iommu *iommu,
29773007 struct vfio_iommu_type1_dirty_bitmap_get range ;
29783008 unsigned long pgshift ;
29793009 size_t data_size = dirty .argsz - minsz ;
2980- size_t iommu_pgsize ;
3010+ size_t size , iommu_pgsize ;
3011+ dma_addr_t iova , iova_end ;
29813012
29823013 if (!data_size || data_size < sizeof (range ))
29833014 return - EINVAL ;
@@ -2986,14 +3017,24 @@ static int vfio_iommu_type1_dirty_pages(struct vfio_iommu *iommu,
29863017 sizeof (range )))
29873018 return - EFAULT ;
29883019
2989- if (range .iova + range .size < range .iova )
3020+ iova = range .iova ;
3021+ size = range .size ;
3022+
3023+ if (iova != range .iova || size != range .size )
3024+ return - EOVERFLOW ;
3025+
3026+ if (!size )
29903027 return - EINVAL ;
3028+
3029+ if (check_add_overflow (iova , size - 1 , & iova_end ))
3030+ return - EOVERFLOW ;
3031+
29913032 if (!access_ok ((void __user * )range .bitmap .data ,
29923033 range .bitmap .size ))
29933034 return - EINVAL ;
29943035
29953036 pgshift = __ffs (range .bitmap .pgsize );
2996- ret = verify_bitmap_size (range . size >> pgshift ,
3037+ ret = verify_bitmap_size (size >> pgshift ,
29973038 range .bitmap .size );
29983039 if (ret )
29993040 return ret ;
@@ -3007,19 +3048,18 @@ static int vfio_iommu_type1_dirty_pages(struct vfio_iommu *iommu,
30073048 ret = - EINVAL ;
30083049 goto out_unlock ;
30093050 }
3010- if (range . iova & (iommu_pgsize - 1 )) {
3051+ if (iova & (iommu_pgsize - 1 )) {
30113052 ret = - EINVAL ;
30123053 goto out_unlock ;
30133054 }
3014- if (! range . size || range . size & (iommu_pgsize - 1 )) {
3055+ if (size & (iommu_pgsize - 1 )) {
30153056 ret = - EINVAL ;
30163057 goto out_unlock ;
30173058 }
30183059
30193060 if (iommu -> dirty_page_tracking )
30203061 ret = vfio_iova_dirty_bitmap (range .bitmap .data ,
3021- iommu , range .iova ,
3022- range .size ,
3062+ iommu , iova , size ,
30233063 range .bitmap .pgsize );
30243064 else
30253065 ret = - EINVAL ;
0 commit comments