Skip to content

Commit f06ac79

Browse files
slpalexandruag
authored andcommitted
mmap: get file size with seek instead of metadata
Currently mmap::check_file_offset attempts to validate the backing object by checking, among other things, its size to confirm the mapping will fit on it. This check is implemented by using std::fs::metadata to obtain the file size, but this approach doesn't work when the backing object is a block or char device, as the returned value is always zero. In this commit, we replace the use of std::fs:metadata with std::io::Seek::seek(SeekEnd(0)), which works fine even with special files such as block and char devices. As a reference, this is the method that QEMU uses for the same goal. Fixes: #195 Signed-off-by: Sergio Lopez <[email protected]>
1 parent fc7153a commit f06ac79

File tree

2 files changed

+16
-5
lines changed

2 files changed

+16
-5
lines changed

src/mmap.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ use std::borrow::Borrow;
1616
use std::error;
1717
use std::fmt;
1818
use std::io::{Read, Write};
19+
#[cfg(unix)]
20+
use std::io::{Seek, SeekFrom};
1921
use std::ops::Deref;
2022
use std::result;
2123
use std::sync::atomic::Ordering;
@@ -116,14 +118,17 @@ pub fn check_file_offset(
116118
file_offset: &FileOffset,
117119
size: usize,
118120
) -> result::Result<(), MmapRegionError> {
119-
let file = file_offset.file();
121+
let mut file = file_offset.file();
120122
let start = file_offset.start();
121123

122124
if let Some(end) = start.checked_add(size as u64) {
123-
if let Ok(metadata) = file.metadata() {
124-
if metadata.len() < end {
125-
return Err(MmapRegionError::MappingPastEof);
126-
}
125+
let filesize = file
126+
.seek(SeekFrom::End(0))
127+
.map_err(MmapRegionError::SeekEnd)?;
128+
file.seek(SeekFrom::Start(0))
129+
.map_err(MmapRegionError::SeekStart)?;
130+
if filesize < end {
131+
return Err(MmapRegionError::MappingPastEof);
127132
}
128133
} else {
129134
return Err(MmapRegionError::InvalidOffsetLength);

src/mmap_unix.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ pub enum Error {
3737
MappingPastEof,
3838
/// The `mmap` call returned an error.
3939
Mmap(io::Error),
40+
/// Seeking the end of the file returned an error.
41+
SeekEnd(io::Error),
42+
/// Seeking the start of the file returned an error.
43+
SeekStart(io::Error),
4044
}
4145

4246
impl fmt::Display for Error {
@@ -60,6 +64,8 @@ impl fmt::Display for Error {
6064
"The specified file offset and length is greater then file length"
6165
),
6266
Error::Mmap(error) => write!(f, "{}", error),
67+
Error::SeekEnd(error) => write!(f, "Error seeking the end of the file: {}", error),
68+
Error::SeekStart(error) => write!(f, "Error seeking the start of the file: {}", error),
6369
}
6470
}
6571
}

0 commit comments

Comments
 (0)