Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(fdtable): add CLOEXEC flag #162

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions api/ruxos_posix_api/src/imp/execve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,14 @@ pub fn sys_execve(pathname: *const c_char, argv: usize, envp: usize) -> ! {
stack.stack_size()
);

current()
.fs
.lock()
.as_mut()
.unwrap()
.fd_table
.do_close_on_exec();

set_sp_and_jmp(sp, entry);
}

Expand Down
107 changes: 63 additions & 44 deletions api/ruxos_posix_api/src/imp/fd_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

use core::ffi::c_int;

use axerrno::{LinuxError, LinuxResult};
use axerrno::LinuxError;
use ruxfdtable::{RuxStat, RuxTimeSpec};
use ruxtask::current;
pub use ruxtask::fs::{add_file_like, close_file_like, get_file_like, RUX_FILE_LIMIT};
Expand Down Expand Up @@ -133,44 +133,40 @@ pub fn sys_close(fd: c_int) -> c_int {
syscall_body!(sys_close, close_file_like(fd).map(|_| 0))
}

fn dup_fd(old_fd: c_int) -> LinuxResult<c_int> {
let f = get_file_like(old_fd)?;
let new_fd = add_file_like(f)?;
Ok(new_fd as _)
}

/// Duplicate a file descriptor.
pub fn sys_dup(old_fd: c_int) -> c_int {
debug!("sys_dup <= {}", old_fd);
syscall_body!(sys_dup, dup_fd(old_fd))
syscall_body!(sys_dup, {
let binding_task = current();
let mut binding_fs = binding_task.fs.lock();
let new_fd = binding_fs.as_mut().unwrap().fd_table.dup(old_fd as _)?;
Ok(new_fd as c_int)
})
}

/// Duplicate a file descriptor, but it uses the file descriptor number specified in `new_fd`.
///
/// TODO: `dup2` should forcibly close new_fd if it is already opened.
/// The close-on-exec flag for the duplicate descriptor is off.
pub fn sys_dup2(old_fd: c_int, new_fd: c_int) -> c_int {
debug!("sys_dup2 <= old_fd: {}, new_fd: {}", old_fd, new_fd);
syscall_body!(sys_dup2, {
if old_fd == new_fd {
let r = sys_fcntl(old_fd, ctypes::F_GETFD as _, 0);
if r >= 0 {
return Ok(old_fd);
} else {
return Ok(r);
}
// check if `oldfd` isn't an open file descriptor. If it not, return `EBADF`
get_file_like(old_fd as _)?;
return Ok(new_fd);
}
if new_fd as usize >= RUX_FILE_LIMIT {
return Err(LinuxError::EBADF);
}
close_file_like(new_fd as _)?;

let f = get_file_like(old_fd as _)?;
let binding_task = current();
let mut binding_fs = binding_task.fs.lock();
let fd_table = &mut binding_fs.as_mut().unwrap().fd_table;
fd_table
.add_at(new_fd as usize, f)
.ok_or(LinuxError::EMFILE)?;
// The steps of closing and reusing the file descriptor newfd are performed atomically.
current()
.fs
.lock()
.as_mut()
.unwrap()
.fd_table
.dup3(old_fd as _, new_fd as _, false)?;

Ok(new_fd)
})
Expand All @@ -187,14 +183,15 @@ pub fn sys_dup3(old_fd: c_int, new_fd: c_int, flags: c_int) -> c_int {
if old_fd == new_fd {
return Err(LinuxError::EINVAL);
}
sys_dup2(old_fd, new_fd);
if flags as u32 & ctypes::O_CLOEXEC != 0 {
sys_fcntl(
new_fd,
ctypes::F_SETFD as c_int,
ctypes::FD_CLOEXEC as usize,
);
}
let cloexec = (flags as u32 & ctypes::O_CLOEXEC) != 0;
let binding_task = current();
let mut binding_fs = binding_task.fs.lock();
binding_fs
.as_mut()
.unwrap()
.fd_table
.dup3(old_fd as _, new_fd as _, cloexec)?;

Ok(new_fd)
})
}
Expand All @@ -206,15 +203,39 @@ pub fn sys_fcntl(fd: c_int, cmd: c_int, arg: usize) -> c_int {
debug!("sys_fcntl <= fd: {} cmd: {} arg: {}", fd, cmd, arg);
syscall_body!(sys_fcntl, {
match cmd as u32 {
ctypes::F_DUPFD => dup_fd(fd),
ctypes::F_DUPFD => {
let new_fd = current()
.fs
.lock()
.as_mut()
.unwrap()
.fd_table
.dup_with_low_bound(fd as _, arg as _, false)?;
Ok(new_fd as _)
}
ctypes::F_GETFD => {
// Return (as the function result) the file descriptor flags; the arg is ignored.
// temporary unsupport CLOEXEC flag
Ok(0)
let binding_task = current();
let mut binding_fs = binding_task.fs.lock();
let fd_table = &mut binding_fs.as_mut().unwrap().fd_table;
if fd_table.get(fd as _).is_none() {
return Err(LinuxError::EBADF);
}
let cloexec = if fd_table.get_cloexec(fd as _) {
ctypes::FD_CLOEXEC
} else {
0
};
Ok(cloexec as _)
}
ctypes::F_DUPFD_CLOEXEC => {
// TODO: Change fd flags
dup_fd(fd)
let new_fd = current()
.fs
.lock()
.as_mut()
.unwrap()
.fd_table
.dup_with_low_bound(fd as _, arg as _, true)?;
Ok(new_fd as _)
}
ctypes::F_SETFL => {
if fd == 0 || fd == 1 || fd == 2 {
Expand All @@ -238,16 +259,14 @@ pub fn sys_fcntl(fd: c_int, cmd: c_int, arg: usize) -> c_int {
Ok(flags as c_int)
}
ctypes::F_SETFD => {
if arg == 0 || arg == 1 || arg == 2 {
return Ok(0);
}
let cloexec = (arg as u32 & ctypes::FD_CLOEXEC) == 1;
let binding_task = current();
let mut binding_fs = binding_task.fs.lock();
let fd_table = &mut binding_fs.as_mut().unwrap().fd_table;
fd_table
.add_at(arg, get_file_like(fd)?)
.ok_or(LinuxError::EMFILE)?;
let _ = close_file_like(fd);
if fd_table.get(fd as _).is_none() {
return Err(LinuxError::EBADF);
}
fd_table.set_cloexec(fd as _, cloexec);
Ok(0)
}
_ => {
Expand Down
6 changes: 3 additions & 3 deletions api/ruxos_posix_api/src/imp/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ pub fn sys_open(filename: *const c_char, flags: c_int, mode: ctypes::mode_t) ->
syscall_body!(sys_open, {
let options = flags_to_options(flags, mode);
let file = ruxfs::fops::File::open(filename?, &options)?;
File::new(file).add_to_fd_table()
File::new(file).add_to_fd_table(flags as usize)
})
}

Expand All @@ -94,7 +94,7 @@ pub fn sys_openat(fd: usize, path: *const c_char, flags: c_int, mode: ctypes::mo
.write()
.open_dir_at(path?, &options)?
};
Directory::new(dir).add_to_fd_table()
Directory::new(dir).add_to_fd_table(flags as usize)
} else {
let file = if fd == ctypes::AT_FDCWD {
ruxfs::fops::File::open(path?, &options)?
Expand All @@ -104,7 +104,7 @@ pub fn sys_openat(fd: usize, path: *const c_char, flags: c_int, mode: ctypes::mo
.write()
.open_file_at(path?, &options)?
};
File::new(file).add_to_fd_table()
File::new(file).add_to_fd_table(flags as usize)
}
})
}
Expand Down
8 changes: 4 additions & 4 deletions api/ruxos_posix_api/src/imp/io_mpx/epoll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,14 +160,14 @@ impl FileLike for EpollInstance {
/// Creates a new epoll instance.
///
/// It returns a file descriptor referring to the new epoll instance.
pub fn sys_epoll_create(size: c_int) -> c_int {
debug!("sys_epoll_create <= {}", size);
pub fn sys_epoll_create1(flags: c_int) -> c_int {
debug!("sys_epoll_create <= {}", flags);
syscall_body!(sys_epoll_create, {
if size < 0 {
if flags < 0 {
return Err(LinuxError::EINVAL);
}
let epoll_instance = EpollInstance::new(0);
add_file_like(Arc::new(epoll_instance))
add_file_like(Arc::new(epoll_instance), flags as usize)
})
}

Expand Down
2 changes: 1 addition & 1 deletion api/ruxos_posix_api/src/imp/io_mpx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ mod poll;
mod select;

#[cfg(feature = "epoll")]
pub use self::epoll::{sys_epoll_create, sys_epoll_ctl, sys_epoll_pwait, sys_epoll_wait};
pub use self::epoll::{sys_epoll_create1, sys_epoll_ctl, sys_epoll_pwait, sys_epoll_wait};
#[cfg(feature = "poll")]
pub use self::poll::{sys_poll, sys_ppoll};
#[cfg(feature = "select")]
Expand Down
25 changes: 13 additions & 12 deletions api/ruxos_posix_api/src/imp/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ pub enum Socket {
}

impl Socket {
fn add_to_fd_table(self) -> LinuxResult<c_int> {
ruxtask::fs::add_file_like(Arc::new(self))
fn add_to_fd_table(self, flags: usize) -> LinuxResult<c_int> {
ruxtask::fs::add_file_like(Arc::new(self), flags)
}

fn from_fd(fd: c_int) -> LinuxResult<Arc<Self>> {
Expand Down Expand Up @@ -338,25 +338,26 @@ fn from_sockaddr(
pub fn sys_socket(domain: c_int, socktype: c_int, protocol: c_int) -> c_int {
debug!("sys_socket <= {} {} {}", domain, socktype, protocol);
let (domain, socktype, protocol) = (domain as u32, socktype as u32, protocol as u32);
pub const _SOCK_STREAM_NONBLOCK: u32 = ctypes::SOCK_STREAM | ctypes::SOCK_NONBLOCK;
let fdflags = (socktype & ctypes::SOCK_CLOEXEC) as usize;
let nonblock = (socktype & ctypes::SOCK_NONBLOCK) != 0;
let socktype = socktype & !ctypes::SOCK_CLOEXEC & !ctypes::SOCK_NONBLOCK;
syscall_body!(sys_socket, {
match (domain, socktype, protocol) {
(ctypes::AF_INET, ctypes::SOCK_STREAM, ctypes::IPPROTO_TCP)
| (ctypes::AF_INET, ctypes::SOCK_STREAM, 0) => {
Socket::Tcp(Mutex::new(TcpSocket::new())).add_to_fd_table()
let tcp_socket = TcpSocket::new();
if nonblock {
tcp_socket.set_nonblocking(true);
}
Socket::Tcp(Mutex::new(tcp_socket)).add_to_fd_table(fdflags)
}
(ctypes::AF_INET, ctypes::SOCK_DGRAM, ctypes::IPPROTO_UDP)
| (ctypes::AF_INET, ctypes::SOCK_DGRAM, 0) => {
Socket::Udp(Mutex::new(UdpSocket::new())).add_to_fd_table()
}
(ctypes::AF_INET, _SOCK_STREAM_NONBLOCK, ctypes::IPPROTO_TCP) => {
let tcp_socket = TcpSocket::new();
tcp_socket.set_nonblocking(true);
Socket::Tcp(Mutex::new(tcp_socket)).add_to_fd_table()
Socket::Udp(Mutex::new(UdpSocket::new())).add_to_fd_table(fdflags)
}
(ctypes::AF_UNIX, ctypes::SOCK_STREAM, 0) => {
Socket::Unix(Mutex::new(UnixSocket::new(UnixSocketType::SockStream)))
.add_to_fd_table()
.add_to_fd_table(fdflags)
}
_ => Err(LinuxError::EINVAL),
}
Expand Down Expand Up @@ -558,7 +559,7 @@ pub unsafe fn sys_accept(
let socket = Socket::from_fd(socket_fd)?;
let new_socket = socket.accept()?;
let addr = new_socket.peer_addr()?;
let new_fd = Socket::add_to_fd_table(new_socket)?;
let new_fd = Socket::add_to_fd_table(new_socket, 0)?;
match addr {
UnifiedSocketAddress::Net(addr) => unsafe {
(*socket_addr, *socket_len) = into_sockaddr(addr);
Expand Down
4 changes: 2 additions & 2 deletions api/ruxos_posix_api/src/imp/pipe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,8 +233,8 @@ pub fn sys_pipe(fds: &mut [c_int]) -> c_int {
}

let (read_end, write_end) = Pipe::new();
let read_fd = add_file_like(Arc::new(read_end))?;
let write_fd = add_file_like(Arc::new(write_end)).inspect_err(|_| {
let read_fd = add_file_like(Arc::new(read_end), 0)?;
let write_fd = add_file_like(Arc::new(write_end), 0).inspect_err(|_| {
close_file_like(read_fd).ok();
})?;

Expand Down
2 changes: 1 addition & 1 deletion api/ruxos_posix_api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ pub use imp::fs::{
sys_rmdir, sys_stat, sys_unlink, sys_unlinkat,
};
#[cfg(feature = "epoll")]
pub use imp::io_mpx::{sys_epoll_create, sys_epoll_ctl, sys_epoll_pwait, sys_epoll_wait};
pub use imp::io_mpx::{sys_epoll_create1, sys_epoll_ctl, sys_epoll_pwait, sys_epoll_wait};
#[cfg(feature = "poll")]
pub use imp::io_mpx::{sys_poll, sys_ppoll};
#[cfg(feature = "select")]
Expand Down
19 changes: 19 additions & 0 deletions crates/flatten_objects/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,25 @@ impl<T, const CAP: usize> FlattenObjects<T, CAP> {
Some(id)
}

/// Add an object and assign it a unique ID, but only search for IDs starting from `low_bound`.
///
/// Returns the assigned ID if an available slot is found; otherwise, returns `None`.
pub fn add_with_low_bound(&mut self, value: T, low_bound: usize) -> Option<usize> {
let id = if low_bound == 0 {
self.id_bitmap.first_false_index()
} else {
self.id_bitmap.next_false_index(low_bound - 1)
}?;
if id < CAP {
self.count += 1;
self.id_bitmap.set(id, true);
self.objects[id].write(value);
Some(id)
} else {
None
}
}

/// Removes the object with the given ID.
///
/// Returns the object if there is one assigned to the ID. Otherwise,
Expand Down
22 changes: 13 additions & 9 deletions modules/ruxtask/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@
name = "ruxtask"
version = "0.1.0"
edition = "2021"
authors = [
"Yuekai Jia <[email protected]>",
"AuYang261 <[email protected]>",
]
authors = ["Yuekai Jia <[email protected]>", "AuYang261 <[email protected]>"]
description = "Ruxos task management module"
license = "GPL-3.0-or-later OR Apache-2.0"
homepage = "https://github.com/syswonder/ruxos"
Expand All @@ -15,8 +12,15 @@ repository = "https://github.com/syswonder/ruxos/tree/main/modules/ruxtask"
default = ["fs"]

multitask = [
"dep:ruxconfig", "dep:percpu", "dep:spinlock", "dep:lazy_init", "dep:memory_addr",
"dep:scheduler", "dep:timer_list", "kernel_guard", "dep:crate_interface"
"dep:ruxconfig",
"dep:percpu",
"dep:spinlock",
"dep:lazy_init",
"dep:memory_addr",
"dep:scheduler",
"dep:timer_list",
"kernel_guard",
"dep:crate_interface",
]
irq = []
tls = ["ruxhal/tls"]
Expand Down Expand Up @@ -53,16 +57,16 @@ kernel_guard = { version = "0.1.0", optional = true }
crate_interface = { version = "0.1.1", optional = true }
flatten_objects = { path = "../../crates/flatten_objects" }
spin = "0.9"
axio ={ path = "../../crates/axio" }
axio = { path = "../../crates/axio" }
lazy_static = { version = "1.4", features = ["spin_no_std"] }
page_table = { path = "../../crates/page_table" }
page_table_entry = { path = "../../crates/page_table_entry" }

bitmaps = { version = "3.2", default-features = false }
# for testing
axfs_vfs = { path = "../../crates/axfs_vfs"}
axfs_vfs = { path = "../../crates/axfs_vfs" }

[dev-dependencies]
rand = "0.8"
ruxhal = { path = "../ruxhal", features = ["fp_simd"] }
ruxtask = { path = ".", features = ["test"] }

Loading
Loading