Perform cloexec logic in kernel
This commit is contained in:
@@ -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>,
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user