Skip to content

Commit cc0a191

Browse files
jiangliueryugey
authored andcommitted
ptfs: use BorrowedFd instead of RawFd when possible
Use BorrowedFd instead of RawFd when possible. By using BorrowedFd we can explicitly manage the lifetime of the underlying RawFd, to avoid misusing after file close. Signed-off-by: Jiang Liu <[email protected]>
1 parent 245cc7c commit cc0a191

File tree

4 files changed

+40
-31
lines changed

4 files changed

+40
-31
lines changed

src/passthrough/file_handle.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::ffi::CStr;
88
use std::fmt::{Debug, Formatter};
99
use std::fs::File;
1010
use std::io;
11+
use std::os::fd::AsFd;
1112
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
1213
use std::sync::Arc;
1314

@@ -283,7 +284,7 @@ impl Debug for OpenableFileHandle {
283284
write!(
284285
f,
285286
"Openable file handle: mountfd {}, type {}, len {}",
286-
self.mount_fd.as_raw_fd(),
287+
self.mount_fd.as_fd().as_raw_fd(),
287288
fh.handle_type,
288289
fh.handle_bytes
289290
)
@@ -295,7 +296,7 @@ impl OpenableFileHandle {
295296
pub fn open(&self, flags: libc::c_int) -> io::Result<File> {
296297
let ret = unsafe {
297298
open_by_handle_at(
298-
self.mount_fd.as_raw_fd(),
299+
self.mount_fd.as_fd().as_raw_fd(),
299300
self.handle.handle.wrapper.as_fam_struct_ptr(),
300301
flags,
301302
)

src/passthrough/mod.rs

+14-10
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use std::fs::File;
1818
use std::io;
1919
use std::marker::PhantomData;
2020
use std::ops::{Deref, DerefMut};
21+
use std::os::fd::{AsFd, BorrowedFd};
2122
use std::os::unix::ffi::OsStringExt;
2223
use std::os::unix::io::{AsRawFd, RawFd};
2324
use std::path::PathBuf;
@@ -85,6 +86,15 @@ impl AsRawFd for InodeFile<'_> {
8586
}
8687
}
8788

89+
impl AsFd for InodeFile<'_> {
90+
fn as_fd(&self) -> BorrowedFd<'_> {
91+
match self {
92+
Self::Owned(file) => file.as_fd(),
93+
Self::Ref(file_ref) => file_ref.as_fd(),
94+
}
95+
}
96+
}
97+
8898
#[derive(Debug)]
8999
enum InodeHandle {
90100
File(File),
@@ -268,12 +278,8 @@ impl HandleData {
268278
(self.lock.lock().unwrap(), &self.file)
269279
}
270280

271-
// When making use of the underlying RawFd, the caller must ensure that the Arc<HandleData>
272-
// object is within scope. Otherwise it may cause race window to access wrong target fd.
273-
// By introducing this method, we could explicitly audit all callers making use of the
274-
// underlying RawFd.
275-
fn get_handle_raw_fd(&self) -> RawFd {
276-
self.file.as_raw_fd()
281+
fn borrow_fd(&self) -> BorrowedFd {
282+
self.file.as_fd()
277283
}
278284

279285
fn get_flags(&self) -> u32 {
@@ -977,10 +983,8 @@ mod tests {
977983
use crate::api::{Vfs, VfsOptions};
978984
use caps::{CapSet, Capability};
979985
use log;
980-
use std::fs::File;
981986
use std::io::Read;
982987
use std::ops::Deref;
983-
use std::os::unix::io::FromRawFd;
984988
use std::os::unix::prelude::MetadataExt;
985989
use vmm_sys_util::{tempdir::TempDir, tempfile::TempFile};
986990

@@ -1231,7 +1235,7 @@ mod tests {
12311235
};
12321236
let (entry, handle, _, _) = fs.create(&ctx, ROOT_ID, &fname, args).unwrap();
12331237
let handle_data = fs.handle_map.get(handle.unwrap(), entry.inode).unwrap();
1234-
let mut f = unsafe { File::from_raw_fd(handle_data.get_handle_raw_fd()) };
1238+
let (_guard, mut f) = handle_data.get_file_mut();
12351239
let mut buf = [0; 4];
12361240
// Buggy code return EBADF on read
12371241
let n = f.read(&mut buf).unwrap();
@@ -1244,7 +1248,7 @@ mod tests {
12441248
.open(&ctx, entry.inode, libc::O_WRONLY as u32, 0)
12451249
.unwrap();
12461250
let handle_data = fs.handle_map.get(handle.unwrap(), entry.inode).unwrap();
1247-
let mut f = unsafe { File::from_raw_fd(handle_data.get_handle_raw_fd()) };
1251+
let (_guard, mut f) = handle_data.get_file_mut();
12481252
let mut buf = [0; 4];
12491253
let n = f.read(&mut buf).unwrap();
12501254
assert_eq!(n, 0);

src/passthrough/mount_fd.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::collections::{HashMap, HashSet};
55
use std::ffi::CString;
66
use std::fs::File;
77
use std::io::{self, Read, Seek};
8+
use std::os::fd::{AsFd, BorrowedFd};
89
use std::os::unix::io::{AsRawFd, RawFd};
910
use std::sync::{Arc, Mutex, RwLock, Weak};
1011

@@ -22,9 +23,9 @@ pub struct MountFd {
2223
map: Weak<RwLock<HashMap<MountId, Weak<MountFd>>>>,
2324
}
2425

25-
impl AsRawFd for MountFd {
26-
fn as_raw_fd(&self) -> RawFd {
27-
self.file.as_raw_fd()
26+
impl AsFd for MountFd {
27+
fn as_fd(&self) -> BorrowedFd {
28+
self.file.as_fd()
2829
}
2930
}
3031

@@ -464,7 +465,7 @@ mod tests {
464465
assert_eq!(mount_fds.map.read().unwrap().len(), 1);
465466

466467
// Ensure fd1 and fd2 are the same object.
467-
assert_eq!(fd1.as_raw_fd(), fd2.as_raw_fd());
468+
assert_eq!(fd1.as_fd().as_raw_fd(), fd2.as_fd().as_raw_fd());
468469

469470
drop(fd1);
470471
assert_eq!(Arc::strong_count(&fd2), 1);

src/passthrough/sync_io.rs

+18-15
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ impl<S: BitmapSlice + Send + Sync> PassthroughFs<S> {
152152
type_: u32::from(dirent64.d_ty),
153153
name,
154154
},
155-
data.get_handle_raw_fd(),
155+
data.borrow_fd().as_raw_fd(),
156156
)
157157
};
158158

@@ -663,7 +663,7 @@ impl<S: BitmapSlice + Send + Sync> FileSystem for PassthroughFs<S> {
663663
// Manually implement File::try_clone() by borrowing fd of data.file instead of dup().
664664
// It's safe because the `data` variable's lifetime spans the whole function,
665665
// so data.file won't be closed.
666-
let f = unsafe { File::from_raw_fd(data.get_handle_raw_fd()) };
666+
let f = unsafe { File::from_raw_fd(data.borrow_fd().as_raw_fd()) };
667667

668668
self.check_fd_flags(data, f.as_raw_fd(), flags)?;
669669

@@ -690,7 +690,7 @@ impl<S: BitmapSlice + Send + Sync> FileSystem for PassthroughFs<S> {
690690
// Manually implement File::try_clone() by borrowing fd of data.file instead of dup().
691691
// It's safe because the `data` variable's lifetime spans the whole function,
692692
// so data.file won't be closed.
693-
let f = unsafe { File::from_raw_fd(data.get_handle_raw_fd()) };
693+
let f = unsafe { File::from_raw_fd(data.borrow_fd().as_raw_fd()) };
694694

695695
self.check_fd_flags(data, f.as_raw_fd(), flags)?;
696696

@@ -732,7 +732,7 @@ impl<S: BitmapSlice + Send + Sync> FileSystem for PassthroughFs<S> {
732732
let inode_data = self.inode_map.get(inode)?;
733733

734734
enum Data {
735-
Handle(Arc<HandleData>, RawFd),
735+
Handle(Arc<HandleData>),
736736
ProcPath(CString),
737737
}
738738

@@ -745,8 +745,7 @@ impl<S: BitmapSlice + Send + Sync> FileSystem for PassthroughFs<S> {
745745
// If we have a handle then use it otherwise get a new fd from the inode.
746746
if let Some(handle) = handle {
747747
let hd = self.handle_map.get(handle, inode)?;
748-
let fd = hd.get_handle_raw_fd();
749-
Data::Handle(hd, fd)
748+
Data::Handle(hd)
750749
} else {
751750
let pathname = CString::new(format!("{}", file.as_raw_fd()))
752751
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
@@ -762,7 +761,7 @@ impl<S: BitmapSlice + Send + Sync> FileSystem for PassthroughFs<S> {
762761
// Safe because this doesn't modify any memory and we check the return value.
763762
let res = unsafe {
764763
match data {
765-
Data::Handle(_, fd) => libc::fchmod(fd, attr.st_mode),
764+
Data::Handle(ref h) => libc::fchmod(h.borrow_fd().as_raw_fd(), attr.st_mode),
766765
Data::ProcPath(ref p) => {
767766
libc::fchmodat(self.proc_self_fd.as_raw_fd(), p.as_ptr(), attr.st_mode, 0)
768767
}
@@ -817,7 +816,9 @@ impl<S: BitmapSlice + Send + Sync> FileSystem for PassthroughFs<S> {
817816

818817
// Safe because this doesn't modify any memory and we check the return value.
819818
let res = match data {
820-
Data::Handle(_, fd) => unsafe { libc::ftruncate(fd, attr.st_size) },
819+
Data::Handle(ref h) => unsafe {
820+
libc::ftruncate(h.borrow_fd().as_raw_fd(), attr.st_size)
821+
},
821822
_ => {
822823
// There is no `ftruncateat` so we need to get a new fd and truncate it.
823824
let f = self.open_inode(inode, libc::O_NONBLOCK | libc::O_RDWR)?;
@@ -857,7 +858,9 @@ impl<S: BitmapSlice + Send + Sync> FileSystem for PassthroughFs<S> {
857858

858859
// Safe because this doesn't modify any memory and we check the return value.
859860
let res = match data {
860-
Data::Handle(_, fd) => unsafe { libc::futimens(fd, tvs.as_ptr()) },
861+
Data::Handle(ref h) => unsafe {
862+
libc::futimens(h.borrow_fd().as_raw_fd(), tvs.as_ptr())
863+
},
861864
Data::ProcPath(ref p) => unsafe {
862865
libc::utimensat(self.proc_self_fd.as_raw_fd(), p.as_ptr(), tvs.as_ptr(), 0)
863866
},
@@ -1043,7 +1046,7 @@ impl<S: BitmapSlice + Send + Sync> FileSystem for PassthroughFs<S> {
10431046
// behavior by doing the same thing (dup-ing the fd and then immediately closing it). Safe
10441047
// because this doesn't modify any memory and we check the return values.
10451048
unsafe {
1046-
let newfd = libc::dup(data.get_handle_raw_fd());
1049+
let newfd = libc::dup(data.borrow_fd().as_raw_fd());
10471050
if newfd < 0 {
10481051
return Err(io::Error::last_os_error());
10491052
}
@@ -1064,14 +1067,14 @@ impl<S: BitmapSlice + Send + Sync> FileSystem for PassthroughFs<S> {
10641067
handle: Handle,
10651068
) -> io::Result<()> {
10661069
let data = self.get_data(handle, inode, libc::O_RDONLY)?;
1067-
let fd = data.get_handle_raw_fd();
1070+
let fd = data.borrow_fd();
10681071

10691072
// Safe because this doesn't modify any memory and we check the return value.
10701073
let res = unsafe {
10711074
if datasync {
1072-
libc::fdatasync(fd)
1075+
libc::fdatasync(fd.as_raw_fd())
10731076
} else {
1074-
libc::fsync(fd)
1077+
libc::fsync(fd.as_raw_fd())
10751078
}
10761079
};
10771080
if res == 0 {
@@ -1276,7 +1279,7 @@ impl<S: BitmapSlice + Send + Sync> FileSystem for PassthroughFs<S> {
12761279
) -> io::Result<()> {
12771280
// Let the Arc<HandleData> in scope, otherwise fd may get invalid.
12781281
let data = self.get_data(handle, inode, libc::O_RDWR)?;
1279-
let fd = data.get_handle_raw_fd();
1282+
let fd = data.borrow_fd();
12801283

12811284
if self.seal_size.load(Ordering::Relaxed) {
12821285
let st = stat_fd(&fd, None)?;
@@ -1292,7 +1295,7 @@ impl<S: BitmapSlice + Send + Sync> FileSystem for PassthroughFs<S> {
12921295
// Safe because this doesn't modify any memory and we check the return value.
12931296
let res = unsafe {
12941297
libc::fallocate64(
1295-
fd,
1298+
fd.as_raw_fd(),
12961299
mode as libc::c_int,
12971300
offset as libc::off64_t,
12981301
length as libc::off64_t,

0 commit comments

Comments
 (0)