From 252d5b3cf3fd7a48fe9d610b59e3d6da9f2c6fe9 Mon Sep 17 00:00:00 2001 From: Dylan Reid Date: Fri, 27 Mar 2020 19:07:59 +0000 Subject: handle mmap of large offsets on 32 bit systems While only 32 bits of address can be mapped, that 32 bits can be offset by further than 32 bits in to a large file. As chirantan points out, the try_mmap call was already casting the usize to u64 on all architectures. Convert the usize offset in mmap to u64 and address users of the API as well. Change-Id: I67aed928ea521049fb51eb7aa61ea4de8b4d096c Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2124879 Reviewed-by: Dylan Reid Tested-by: Dylan Reid Tested-by: kokoro Commit-Queue: Dylan Reid --- sys_util/src/guest_memory.rs | 10 +++++----- sys_util/src/mmap.rs | 22 +++++++++++----------- 2 files changed, 16 insertions(+), 16 deletions(-) (limited to 'sys_util/src') diff --git a/sys_util/src/guest_memory.rs b/sys_util/src/guest_memory.rs index 2390b92..e8f620b 100644 --- a/sys_util/src/guest_memory.rs +++ b/sys_util/src/guest_memory.rs @@ -84,7 +84,7 @@ impl Display for Error { struct MemoryRegion { mapping: MemoryMapping, guest_base: GuestAddress, - memfd_offset: usize, + memfd_offset: u64, } fn region_end(region: &MemoryRegion) -> GuestAddress { @@ -175,7 +175,7 @@ impl GuestMemory { memfd_offset: offset, }); - offset += size; + offset += size as u64; } Ok(GuestMemory { @@ -262,7 +262,7 @@ impl GuestMemory { /// * memfd_offset: usize pub fn with_regions(&self, mut cb: F) -> result::Result<(), E> where - F: FnMut(usize, GuestAddress, usize, usize, usize) -> result::Result<(), E>, + F: FnMut(usize, GuestAddress, usize, usize, u64) -> result::Result<(), E>, { for (index, region) in self.regions.iter().enumerate() { cb( @@ -584,10 +584,10 @@ impl GuestMemory { /// .expect("failed to get offset"); /// assert_eq!(offset, 0x3500); /// ``` - pub fn offset_from_base(&self, guest_addr: GuestAddress) -> Result { + pub fn offset_from_base(&self, guest_addr: GuestAddress) -> Result { for region in self.regions.iter() { if guest_addr >= region.guest_base && guest_addr < region_end(region) { - return Ok(region.memfd_offset + guest_addr.offset_from(region.guest_base) as usize); + return Ok(region.memfd_offset + guest_addr.offset_from(region.guest_base) as u64); } } Err(Error::InvalidGuestAddress(guest_addr)) diff --git a/sys_util/src/mmap.rs b/sys_util/src/mmap.rs index d8ba6b6..006b0a8 100644 --- a/sys_util/src/mmap.rs +++ b/sys_util/src/mmap.rs @@ -164,7 +164,7 @@ impl MemoryMapping { MemoryMapping::from_fd_offset(fd, size, 0) } - pub fn from_fd_offset(fd: &dyn AsRawFd, size: usize, offset: usize) -> Result { + pub fn from_fd_offset(fd: &dyn AsRawFd, size: usize, offset: u64) -> Result { MemoryMapping::from_fd_offset_protection(fd, size, offset, Protection::read_write()) } @@ -177,7 +177,7 @@ impl MemoryMapping { pub fn from_fd_offset_populate( fd: &dyn AsRawFd, size: usize, - offset: usize, + offset: u64, ) -> Result { MemoryMapping::from_fd_offset_flags( fd, @@ -199,7 +199,7 @@ impl MemoryMapping { fn from_fd_offset_flags( fd: &dyn AsRawFd, size: usize, - offset: usize, + offset: u64, flags: c_int, prot: Protection, ) -> Result { @@ -220,7 +220,7 @@ impl MemoryMapping { pub fn from_fd_offset_protection( fd: &dyn AsRawFd, size: usize, - offset: usize, + offset: u64, prot: Protection, ) -> Result { MemoryMapping::from_fd_offset_flags(fd, size, offset, libc::MAP_SHARED, prot) @@ -261,7 +261,7 @@ impl MemoryMapping { addr: *mut u8, fd: &dyn AsRawFd, size: usize, - offset: usize, + offset: u64, prot: Protection, ) -> Result { MemoryMapping::try_mmap( @@ -280,7 +280,7 @@ impl MemoryMapping { size: usize, prot: c_int, flags: c_int, - fd: Option<(&dyn AsRawFd, usize)>, + fd: Option<(&dyn AsRawFd, u64)>, ) -> Result { let mut flags = flags; // If addr is provided, set the FIXED flag, and validate addr alignment @@ -297,7 +297,7 @@ impl MemoryMapping { // If fd is provided, validate fd offset is within bounds let (fd, offset) = match fd { Some((fd, offset)) => { - if offset > libc::off_t::max_value() as usize { + if offset > libc::off_t::max_value() as u64 { return Err(Error::InvalidOffset); } (fd.as_raw_fd(), offset as libc::off_t) @@ -714,7 +714,7 @@ impl MemoryMappingArena { offset: usize, size: usize, fd: &dyn AsRawFd, - fd_offset: usize, + fd_offset: u64, ) -> Result<()> { self.add_fd_offset_protection(offset, size, fd, fd_offset, Protection::read_write()) } @@ -734,7 +734,7 @@ impl MemoryMappingArena { offset: usize, size: usize, fd: &dyn AsRawFd, - fd_offset: usize, + fd_offset: u64, prot: Protection, ) -> Result<()> { self.try_add(offset, size, prot, Some((fd, fd_offset))) @@ -747,7 +747,7 @@ impl MemoryMappingArena { offset: usize, size: usize, prot: Protection, - fd: Option<(&dyn AsRawFd, usize)>, + fd: Option<(&dyn AsRawFd, u64)>, ) -> Result<()> { self.validate_range(offset, size)?; @@ -953,7 +953,7 @@ mod tests { #[test] fn from_fd_offset_invalid() { let fd = unsafe { std::fs::File::from_raw_fd(-1) }; - let res = MemoryMapping::from_fd_offset(&fd, 4096, (libc::off_t::max_value() as usize) + 1) + let res = MemoryMapping::from_fd_offset(&fd, 4096, (libc::off_t::max_value() as u64) + 1) .unwrap_err(); match res { Error::InvalidOffset => {} -- cgit 1.4.1