fs: Fix device socket

validate_raw_fd assumes that the fd passed in was not created by crosvm
and returns EBADF if it sees that the fd has the FD_CLOEXEC flag set.
We can't use it for fds created by the fs device since those do have
that flag set.

We're already taking a `&dyn AsRawFd` as the parameter so just assume
it's valid and clone it directly since there's no safe way to create an
invalid one.

BUG=none
TEST=vm.Fio.virtiofs_dax* tests are no longer failing

Change-Id: I10d9752e0960143fb58a63d2b76f64d34ec464d0
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2809686
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-by: Zach Reizner <zachr@chromium.org>
Commit-Queue: Chirantan Ekbote <chirantan@chromium.org>
This commit is contained in:
Chirantan Ekbote 2021-04-06 19:49:49 +09:00 committed by Commit Bot
parent 401340ee7f
commit 4b47aa7105
4 changed files with 19 additions and 3 deletions

View file

@ -51,3 +51,4 @@ utimensat: 1
prctl: arg0 == PR_SET_SECUREBITS || arg0 == PR_GET_SECUREBITS
capget: 1
capset: 1
fcntl: 1

View file

@ -53,4 +53,5 @@ unlinkat: 1
utimensat: 1
prctl: arg0 == PR_SET_SECUREBITS || arg0 == PR_GET_SECUREBITS
capget: 1
capset: 1
capset: 1
fcntl64: 1

View file

@ -54,3 +54,4 @@ utimensat: 1
prctl: arg0 == PR_SET_SECUREBITS || arg0 == PR_GET_SECUREBITS
capget: 1
capset: 1
fcntl: 1

View file

@ -13,8 +13,8 @@ use std::os::unix::net::{UnixDatagram, UnixStream};
use serde::{Deserialize, Serialize};
use crate::net::UnlinkUnixSeqpacketListener;
use crate::{errno_result, PollToken, Result};
use crate::{net::UnlinkUnixSeqpacketListener, validate_raw_fd};
pub type RawDescriptor = RawFd;
@ -36,6 +36,19 @@ pub trait FromRawDescriptor {
unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Self;
}
/// Clones `fd`, returning a new file descriptor that refers to the same open file description as
/// `fd`. The cloned fd will have the `FD_CLOEXEC` flag set but will not share any other file
/// descriptor flags with `fd`.
pub fn clone_fd(fd: &dyn AsRawFd) -> Result<RawFd> {
// Safe because this doesn't modify any memory and we check the return value.
let ret = unsafe { libc::fcntl(fd.as_raw_fd(), libc::F_DUPFD_CLOEXEC, 0) };
if ret < 0 {
errno_result()
} else {
Ok(ret)
}
}
/// Wraps a RawDescriptor and safely closes it when self falls out of scope.
#[derive(Serialize, Deserialize, Debug, Eq)]
#[serde(transparent)]
@ -108,7 +121,7 @@ impl TryFrom<&dyn AsRawFd> for SafeDescriptor {
fn try_from(fd: &dyn AsRawFd) -> std::result::Result<Self, Self::Error> {
Ok(SafeDescriptor {
descriptor: validate_raw_fd(fd.as_raw_fd())?,
descriptor: clone_fd(fd)?,
})
}
}