Perform cloexec logic in kernel

This commit is contained in:
Jeremy Soller
2017-04-16 12:49:54 -06:00
parent ea1150cd9b
commit d036c667a1
8 changed files with 77 additions and 56 deletions

View File

@@ -10,6 +10,8 @@ pub struct File {
pub scheme: SchemeId,
/// The number the scheme uses to refer to this file
pub number: usize,
/// The flags passed to open or fcntl(SETFL)
pub flags: usize,
/// If events are on, this is the event ID
pub event: Option<usize>,
}

View File

@@ -65,17 +65,13 @@ impl Scheme for InitFsScheme {
Err(Error::new(ENOENT))
}
fn dup(&self, id: usize, buf: &[u8]) -> Result<usize> {
fn dup(&self, id: usize, _buf: &[u8]) -> Result<usize> {
let (path, flags, data, mode, seek) = {
let handles = self.handles.read();
let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
(handle.path, handle.flags, handle.data, handle.mode, handle.seek)
};
if buf == b"exec" && flags & O_CLOEXEC == O_CLOEXEC {
return Err(Error::new(EBADF));
}
let id = self.next_id.fetch_add(1, Ordering::SeqCst);
self.handles.write().insert(id, Handle {
path: path,

View File

@@ -6,7 +6,7 @@ use scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT, SchemeId};
use sync::WaitCondition;
use syscall::error::{Error, Result, EAGAIN, EBADF, EINVAL, EPIPE};
use syscall::flag::{F_GETFL, F_SETFL, O_ACCMODE, O_CLOEXEC, O_NONBLOCK};
use syscall::flag::{F_GETFL, F_SETFL, O_ACCMODE, O_NONBLOCK};
use syscall::scheme::Scheme;
/// Pipes list
@@ -50,11 +50,11 @@ impl PipeScheme {
}
impl Scheme for PipeScheme {
fn dup(&self, id: usize, buf: &[u8]) -> Result<usize> {
fn dup(&self, id: usize, _buf: &[u8]) -> Result<usize> {
let mut pipes = pipes_mut();
let read_option = if let Some(pipe) = pipes.0.get(&id) {
Some(pipe.dup(buf)?)
Some(pipe.dup()?)
} else {
None
};
@@ -65,7 +65,7 @@ impl Scheme for PipeScheme {
}
let write_option = if let Some(pipe) = pipes.1.get(&id) {
Some(pipe.dup(buf)?)
Some(pipe.dup()?)
} else {
None
};
@@ -152,20 +152,12 @@ impl PipeRead {
}
}
fn dup(&self, buf: &[u8]) -> Result<Self> {
if buf == b"exec" && self.flags.load(Ordering::SeqCst) & O_CLOEXEC == O_CLOEXEC {
Err(Error::new(EBADF))
} else {
let mut flags = self.flags.load(Ordering::SeqCst);
if buf.is_empty() {
flags &= ! O_CLOEXEC;
}
Ok(PipeRead {
flags: AtomicUsize::new(flags),
condition: self.condition.clone(),
vec: self.vec.clone()
})
}
fn dup(&self) -> Result<Self> {
Ok(PipeRead {
flags: AtomicUsize::new(self.flags.load(Ordering::SeqCst)),
condition: self.condition.clone(),
vec: self.vec.clone()
})
}
fn fcntl(&self, cmd: usize, arg: usize) -> Result<usize> {
@@ -226,20 +218,12 @@ impl PipeWrite {
}
}
fn dup(&self, buf: &[u8]) -> Result<Self> {
if buf == b"exec" && self.flags.load(Ordering::SeqCst) & O_CLOEXEC == O_CLOEXEC {
Err(Error::new(EBADF))
} else {
let mut flags = self.flags.load(Ordering::SeqCst);
if buf.is_empty() {
flags &= ! O_CLOEXEC;
}
Ok(PipeWrite {
flags: AtomicUsize::new(flags),
condition: self.condition.clone(),
vec: self.vec.clone()
})
}
fn dup(&self) -> Result<Self> {
Ok(PipeWrite {
flags: AtomicUsize::new(self.flags.load(Ordering::SeqCst)),
condition: self.condition.clone(),
vec: self.vec.clone()
})
}
fn fcntl(&self, cmd: usize, arg: usize) -> Result<usize> {

View File

@@ -6,7 +6,6 @@ use spin::RwLock;
use context;
use syscall::error::*;
use syscall::flag::O_CLOEXEC;
use syscall::scheme::Scheme;
use scheme::{self, SchemeNamespace, SchemeId};
use scheme::user::{UserInner, UserScheme};
@@ -59,17 +58,13 @@ impl Scheme for RootScheme {
}
}
fn dup(&self, file: usize, buf: &[u8]) -> Result<usize> {
fn dup(&self, file: usize, _buf: &[u8]) -> Result<usize> {
let mut handles = self.handles.write();
let inner = {
let inner = handles.get(&file).ok_or(Error::new(EBADF))?;
inner.clone()
};
if buf == b"exec" && inner.flags & O_CLOEXEC == O_CLOEXEC {
return Err(Error::new(EBADF));
}
let id = self.next_id.fetch_add(1, Ordering::SeqCst);
handles.insert(id, inner);

View File

@@ -36,7 +36,7 @@ pub fn resource() -> Result<Vec<u8>> {
match schemes.get(file.scheme) {
Some(scheme) => scheme.clone(),
None => {
let _ = writeln!(string, " {:>4}: {:>8} {:>8}: no scheme", fd, file.scheme.into(), file.number);
let _ = writeln!(string, " {:>4}: {:>8} {:>8} {:>08X}: no scheme", fd, file.scheme.into(), file.number, file.flags);
continue;
}
}
@@ -46,10 +46,10 @@ pub fn resource() -> Result<Vec<u8>> {
match scheme.fpath(file.number, &mut fpath) {
Ok(path_len) => {
let fname = str::from_utf8(&fpath[..path_len]).unwrap_or("?");
let _ = writeln!(string, " {:>4}: {:>8} {:>8}: {}", fd, file.scheme.into(), file.number, fname);
let _ = writeln!(string, "{:>6}: {:>8} {:>8} {:>08X}: {}", fd, file.scheme.into(), file.number, file.flags, fname);
},
Err(err) => {
let _ = writeln!(string, " {:>4}: {:>8} {:>8}: {}", fd, file.scheme.into(), file.number, err);
let _ = writeln!(string, "{:>6}: {:>8} {:>8} {:>08X}: {}", fd, file.scheme.into(), file.number, file.flags, err);
}
}
}

View File

@@ -6,7 +6,7 @@ use scheme::{self, FileHandle};
use syscall;
use syscall::data::{Packet, Stat};
use syscall::error::*;
use syscall::flag::{MODE_DIR, MODE_FILE};
use syscall::flag::{F_SETFL, O_ACCMODE, O_RDONLY, O_WRONLY, MODE_DIR, MODE_FILE};
pub fn file_op(a: usize, fd: FileHandle, c: usize, d: usize) -> Result<usize> {
let (file, pid, uid, gid) = {
@@ -112,6 +112,7 @@ pub fn open(path: &[u8], flags: usize) -> Result<FileHandle> {
context.add_file(::context::file::File {
scheme: scheme_id,
number: file_id,
flags: flags,
event: None,
}).ok_or(Error::new(EMFILE))
}
@@ -128,12 +129,14 @@ pub fn pipe2(fds: &mut [usize], flags: usize) -> Result<usize> {
let read_fd = context.add_file(::context::file::File {
scheme: scheme_id,
number: read_id,
flags: O_RDONLY | flags & !O_ACCMODE,
event: None,
}).ok_or(Error::new(EMFILE))?;
let write_fd = context.add_file(::context::file::File {
scheme: scheme_id,
number: write_id,
flags: O_WRONLY | flags & !O_ACCMODE,
event: None,
}).ok_or(Error::new(EMFILE))?;
@@ -259,6 +262,7 @@ pub fn dup(fd: FileHandle, buf: &[u8]) -> Result<FileHandle> {
context.add_file(::context::file::File {
scheme: file.scheme,
number: new_id,
flags: file.flags,
event: None,
}).ok_or(Error::new(EMFILE))
}
@@ -293,11 +297,44 @@ pub fn dup2(fd: FileHandle, new_fd: FileHandle, buf: &[u8]) -> Result<FileHandle
context.insert_file(new_fd, ::context::file::File {
scheme: file.scheme,
number: new_id,
flags: file.flags,
event: None,
}).ok_or(Error::new(EBADF))
}
}
// File descriptor controls
pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize) -> Result<usize> {
let file = {
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
let file = context.get_file(fd).ok_or(Error::new(EBADF))?;
file
};
let res = {
let scheme = {
let schemes = scheme::schemes();
let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?;
scheme.clone()
};
scheme.fcntl(file.number, cmd, arg)?
};
if cmd == F_SETFL {
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
let mut files = context.files.lock();
let mut file = files.get_mut(fd.into()).ok_or(Error::new(EBADF))?.ok_or(Error::new(EBADF))?;
let accmode = file.flags & O_ACCMODE;
file.flags = accmode | arg & !O_ACCMODE;
}
Ok(res)
}
/// Register events for file
pub fn fevent(fd: FileHandle, flags: usize) -> Result<usize> {
let file = {

View File

@@ -54,6 +54,7 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize
SYS_CLOSE => close(fd),
SYS_DUP => dup(fd, validate_slice(c as *const u8, d)?).map(FileHandle::into),
SYS_DUP2 => dup2(fd, FileHandle::from(c), validate_slice(d as *const u8, e)?).map(FileHandle::into),
SYS_FCNTL => fcntl(fd, c, d),
SYS_FEVENT => fevent(fd, c),
SYS_FUNMAP => funmap(b),
_ => file_op(a, fd, c, d)

View File

@@ -18,7 +18,7 @@ use scheme::{self, FileHandle};
use syscall;
use syscall::data::Stat;
use syscall::error::*;
use syscall::flag::{CLONE_VFORK, CLONE_VM, CLONE_FS, CLONE_FILES, WNOHANG};
use syscall::flag::{CLONE_VFORK, CLONE_VM, CLONE_FS, CLONE_FILES, O_CLOEXEC, WNOHANG};
use syscall::validate::{validate_slice, validate_slice_mut};
pub fn brk(address: usize) -> Result<usize> {
@@ -268,6 +268,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
Some(context::file::File {
scheme: file.scheme,
number: new_number,
flags: file.flags,
event: None,
})
},
@@ -733,15 +734,19 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
let new_file_option = if let Some(file) = *file_option {
// Duplicate
let result = {
let scheme_option = {
let schemes = scheme::schemes();
schemes.get(file.scheme).map(|scheme| scheme.clone())
};
if let Some(scheme) = scheme_option {
let result = scheme.dup(file.number, b"exec");
result
} else {
if file.flags & O_CLOEXEC == O_CLOEXEC {
Err(Error::new(EBADF))
} else {
let scheme_option = {
let schemes = scheme::schemes();
schemes.get(file.scheme).map(|scheme| scheme.clone())
};
if let Some(scheme) = scheme_option {
let result = scheme.dup(file.number, b"exec");
result
} else {
Err(Error::new(EBADF))
}
}
};
@@ -766,6 +771,7 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
Some(context::file::File {
scheme: file.scheme,
number: new_number,
flags: file.flags,
event: None,
})
},