Skip to content

Commit

Permalink
feat(fdtable): add CLOEXEC flag
Browse files Browse the repository at this point in the history
chore: apply code style fixes and update documentation
  • Loading branch information
Stone749990226 committed Jan 16, 2025
1 parent 06589bf commit 5ead86a
Show file tree
Hide file tree
Showing 15 changed files with 285 additions and 106 deletions.
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
105 changes: 62 additions & 43 deletions api/ruxos_posix_api/src/imp/fd_ops.rs
Original file line number Diff line number Diff line change
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
8 changes: 5 additions & 3 deletions api/ruxos_posix_api/src/imp/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,10 @@ pub fn sys_open(filename: *const c_char, flags: c_int, mode: ctypes::mode_t) ->
let filename = char_ptr_to_str(filename);
debug!("sys_open <= {:?} {:#o} {:#o}", filename, flags, mode);
syscall_body!(sys_open, {
let cloexec = (flags as u32 & ctypes::O_CLOEXEC) != 0;
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(cloexec)
})
}

Expand All @@ -84,6 +85,7 @@ pub fn sys_openat(fd: usize, path: *const c_char, flags: c_int, mode: ctypes::mo
let fd: c_int = fd as c_int;
debug!("sys_openat <= {}, {:?}, {:#o} {:#o}", fd, path, flags, mode);
syscall_body!(sys_openat, {
let cloexec = (flags as u32 & ctypes::O_CLOEXEC) != 0;
let options = flags_to_options(flags, mode);
if (flags as u32) & ctypes::O_DIRECTORY != 0 {
let dir = if fd == ctypes::AT_FDCWD {
Expand All @@ -94,7 +96,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(cloexec)
} else {
let file = if fd == ctypes::AT_FDCWD {
ruxfs::fops::File::open(path?, &options)?
Expand All @@ -104,7 +106,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(cloexec)
}
})
}
Expand Down
9 changes: 5 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,15 @@ 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))
let cloexec = (flags as u32 & ctypes::EPOLL_CLOEXEC) != 0;
add_file_like(Arc::new(epoll_instance), cloexec)
})
}

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
26 changes: 14 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, cloexec: bool) -> LinuxResult<c_int> {
ruxtask::fs::add_file_like(Arc::new(self), cloexec)
}

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 cloexec = (socktype & ctypes::SOCK_CLOEXEC) != 0;
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(cloexec)
}
(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(cloexec)
}
(ctypes::AF_UNIX, ctypes::SOCK_STREAM, 0) => {
Socket::Unix(Mutex::new(UnixSocket::new(UnixSocketType::SockStream)))
.add_to_fd_table()
.add_to_fd_table(cloexec)
}
_ => Err(LinuxError::EINVAL),
}
Expand Down Expand Up @@ -558,7 +559,8 @@ 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 cloexec = false;
let new_fd = Socket::add_to_fd_table(new_socket, cloexec)?;
match addr {
UnifiedSocketAddress::Net(addr) => unsafe {
(*socket_addr, *socket_len) = into_sockaddr(addr);
Expand Down
5 changes: 3 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,9 @@ 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 cloexec = false;
let read_fd = add_file_like(Arc::new(read_end), cloexec)?;
let write_fd = add_file_like(Arc::new(write_end), cloexec).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

0 comments on commit 5ead86a

Please sign in to comment.