[dpdk-dev] vfio: Fix overflow while assigning vfio BAR region offset and size

Message ID 61d1c9174f7f9159d4005dd2cea16c7719cec964.1434462470.git.rahul.lakkireddy@chelsio.com (mailing list archive)
State Changes Requested, archived
Headers

Commit Message

Rahul Lakkireddy June 16, 2015, 2:16 p.m. UTC
  After the commit-id 90a1633b2 (eal/linux: allow to map BARs with MSI-X tables),
VFIO stopped working. On further debug, found that although BAR region
offset and size from vfio are read as u64, they are truncated when assigned to
uint32_t variables resulting in wrong offset being passed for mmap.

The fix is to use uint64_t for offset and size.

Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
---
 lib/librte_eal/linuxapp/eal/eal_pci_vfio.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
  

Comments

Thomas Monjalon June 17, 2015, 12:09 p.m. UTC | #1
Hi Rahul,

2015-06-16 19:46, Rahul Lakkireddy:
> After the commit-id 90a1633b2 (eal/linux: allow to map BARs with MSI-X tables),

Please show this information before the Signed-off-by lines:
Fixes: 90a1633b2347 ("eal/linux: allow to map BARs with MSI-X tables")
generated with this git alias:
fixline = log -1 --abbrev=12 --format='Fixes: %h (\"%s\")'

> VFIO stopped working. On further debug, found that although BAR region

I suppose the whole VFIO didn't stopped working.
Please precise the conditions of the failures (large offset, etc).

> offset and size from vfio are read as u64, they are truncated when assigned to
> uint32_t variables resulting in wrong offset being passed for mmap.
> 
> The fix is to use uint64_t for offset and size.

Unfortunately, it doesn't build for 32-bit target.
  
Rahul Lakkireddy June 18, 2015, 2:23 p.m. UTC | #2
Hi Thomas,

On Wed, Jun 17, 2015 at 14:09:35 +0200, Thomas Monjalon wrote:
> Hi Rahul,
> 
> 2015-06-16 19:46, Rahul Lakkireddy:
> > After the commit-id 90a1633b2 (eal/linux: allow to map BARs with MSI-X tables),
> 
> Please show this information before the Signed-off-by lines:
> Fixes: 90a1633b2347 ("eal/linux: allow to map BARs with MSI-X tables")
> generated with this git alias:
> fixline = log -1 --abbrev=12 --format='Fixes: %h (\"%s\")'
> 

Ok. I'll add it in v2.

> > VFIO stopped working. On further debug, found that although BAR region
> 
> I suppose the whole VFIO didn't stopped working.
> Please precise the conditions of the failures (large offset, etc).

When using vfio, the probe fails over Chelsio T5 after commit-id 90a1633b2
(eal/linux: allow to map BARs with MSI-X tables). While debugging further, found
that the region offset for BAR 2 returned by VFIO is too large to fit in uint32_t.
Also, before the above commit, the region offset was passed to mmap as it is and so
VFIO is working fine before the above commit.

> 
> > offset and size from vfio are read as u64, they are truncated when assigned to
> > uint32_t variables resulting in wrong offset being passed for mmap.
> > 
> > The fix is to use uint64_t for offset and size.
> 
> Unfortunately, it doesn't build for 32-bit target.

I tried on RHEL-6.0 32-bit with T=i686-native-linuxapp-gcc and it built fine.
So, am I missing something here or some option may be?
I will also try out on newer distro like ubuntu 32-bit and confirm.


Thanks,
Rahul.
  

Patch

diff --git a/lib/librte_eal/linuxapp/eal/eal_pci_vfio.c b/lib/librte_eal/linuxapp/eal/eal_pci_vfio.c
index 426953a..d0385ff 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci_vfio.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci_vfio.c
@@ -728,7 +728,7 @@  pci_vfio_map_resource(struct rte_pci_device *dev)
 		struct vfio_region_info reg = { .argsz = sizeof(reg) };
 		void *bar_addr;
 		struct memreg {
-			uint32_t offset, size;
+			uint64_t offset, size;
 		} memreg[2] = {};
 
 		reg.index = i;
@@ -771,7 +771,7 @@  pci_vfio_map_resource(struct rte_pci_device *dev)
 				RTE_LOG(DEBUG, EAL,
 					"Trying to map BAR %d that contains the MSI-X "
 					"table. Trying offsets: "
-					"%04x:%04x, %04x:%04x\n", i,
+					"%04lx:%04lx, %04lx:%04lx\n", i,
 					memreg[0].offset, memreg[0].size,
 					memreg[1].offset, memreg[1].size);
 			}