diff options
author | Alyssa Ross <hi@alyssa.is> | 2020-03-26 12:26:18 +0000 |
---|---|---|
committer | Alyssa Ross <hi@alyssa.is> | 2020-03-26 12:26:18 +0000 |
commit | dbd5f925b6b2f4cb1bf87563be4d24c8ed35689a (patch) | |
tree | 5a51c0af87b6a8bb3dfe43d599cabf96523a7f6f /devices/src/virtio/fs/passthrough.rs | |
parent | 88b7821302043b7ad871fcc0c7748573d0f140e2 (diff) | |
parent | 22964eab8874d41cf0eadf03dfeb1ffb653283e5 (diff) | |
download | crosvm-dbd5f925b6b2f4cb1bf87563be4d24c8ed35689a.tar crosvm-dbd5f925b6b2f4cb1bf87563be4d24c8ed35689a.tar.gz crosvm-dbd5f925b6b2f4cb1bf87563be4d24c8ed35689a.tar.bz2 crosvm-dbd5f925b6b2f4cb1bf87563be4d24c8ed35689a.tar.lz crosvm-dbd5f925b6b2f4cb1bf87563be4d24c8ed35689a.tar.xz crosvm-dbd5f925b6b2f4cb1bf87563be4d24c8ed35689a.tar.zst crosvm-dbd5f925b6b2f4cb1bf87563be4d24c8ed35689a.zip |
Merge remote-tracking branch 'origin/master'
Diffstat (limited to 'devices/src/virtio/fs/passthrough.rs')
-rw-r--r-- | devices/src/virtio/fs/passthrough.rs | 67 |
1 files changed, 64 insertions, 3 deletions
diff --git a/devices/src/virtio/fs/passthrough.rs b/devices/src/virtio/fs/passthrough.rs index bdc1c6f..419d466 100644 --- a/devices/src/virtio/fs/passthrough.rs +++ b/devices/src/virtio/fs/passthrough.rs @@ -395,7 +395,7 @@ impl PassthroughFs { libc::openat( self.proc.as_raw_fd(), pathname.as_ptr(), - (flags | libc::O_CLOEXEC) & (!libc::O_NOFOLLOW), + (flags | libc::O_CLOEXEC) & !(libc::O_NOFOLLOW | libc::O_DIRECT), ) }; if fd < 0 { @@ -592,7 +592,13 @@ impl PassthroughFs { OpenOptions::DIRECT_IO, flags & (libc::O_DIRECTORY as u32) == 0, ), - CachePolicy::Always => opts |= OpenOptions::KEEP_CACHE, + CachePolicy::Always => { + opts |= if flags & (libc::O_DIRECTORY as u32) == 0 { + OpenOptions::KEEP_CACHE + } else { + OpenOptions::CACHE_DIR + } + } _ => {} }; @@ -965,7 +971,8 @@ impl FileSystem for PassthroughFs { libc::openat( data.file.as_raw_fd(), name.as_ptr(), - flags as i32 | libc::O_CREAT | libc::O_CLOEXEC | libc::O_NOFOLLOW, + (flags as i32 | libc::O_CREAT | libc::O_CLOEXEC | libc::O_NOFOLLOW) + & !libc::O_DIRECT, mode & !(umask & 0o777), ) }; @@ -1689,4 +1696,58 @@ impl FileSystem for PassthroughFs { Err(io::Error::from_raw_os_error(libc::ENOTTY)) } } + + fn copy_file_range( + &self, + ctx: Context, + inode_src: Inode, + handle_src: Handle, + offset_src: u64, + inode_dst: Inode, + handle_dst: Handle, + offset_dst: u64, + length: u64, + flags: u64, + ) -> io::Result<usize> { + // We need to change credentials during a write so that the kernel will remove setuid or + // setgid bits from the file if it was written to by someone other than the owner. + let (_uid, _gid) = set_creds(ctx.uid, ctx.gid)?; + let src_data = self + .handles + .read() + .unwrap() + .get(&handle_src) + .filter(|hd| hd.inode == inode_src) + .map(Arc::clone) + .ok_or_else(ebadf)?; + let dst_data = self + .handles + .read() + .unwrap() + .get(&handle_dst) + .filter(|hd| hd.inode == inode_dst) + .map(Arc::clone) + .ok_or_else(ebadf)?; + + let src = src_data.file.lock().as_raw_fd(); + let dst = dst_data.file.lock().as_raw_fd(); + + let res = unsafe { + libc::syscall( + libc::SYS_copy_file_range, + src, + &offset_src, + dst, + offset_dst, + length, + flags, + ) + }; + + if res >= 0 { + Ok(res as usize) + } else { + Err(io::Error::last_os_error()) + } + } } |