From b11e6d2d62d5ad34de6016a3fca31846270d35d0 Mon Sep 17 00:00:00 2001 From: Jianfeng Jiang Date: Tue, 12 Dec 2023 03:28:22 +0000 Subject: [PATCH] Add syscall accept4 --- docs/src/kernel/linux-compatibility.md | 2 +- kernel/aster-nix/src/syscall/accept.rs | 71 +++++++++++++++++++++++--- kernel/aster-nix/src/syscall/mod.rs | 4 +- 3 files changed, 68 insertions(+), 9 deletions(-) diff --git a/docs/src/kernel/linux-compatibility.md b/docs/src/kernel/linux-compatibility.md index 55496dd93..246b5d612 100644 --- a/docs/src/kernel/linux-compatibility.md +++ b/docs/src/kernel/linux-compatibility.md @@ -308,7 +308,7 @@ provided by Linux on x86-64 architecture. | 285 | fallocate | ❌ | | 286 | timerfd_settime | ❌ | | 287 | timerfd_gettime | ❌ | -| 288 | accept4 | ❌ | +| 288 | accept4 | ✅ | | 289 | signalfd4 | ❌ | | 290 | eventfd2 | ✅ | | 291 | epoll_create1 | ✅ | diff --git a/kernel/aster-nix/src/syscall/accept.rs b/kernel/aster-nix/src/syscall/accept.rs index df7984725..d5edfcef3 100644 --- a/kernel/aster-nix/src/syscall/accept.rs +++ b/kernel/aster-nix/src/syscall/accept.rs @@ -2,9 +2,13 @@ use super::{SyscallReturn, SYS_ACCEPT}; use crate::{ - fs::file_table::{FdFlags, FileDesc}, + fs::{ + file_table::{FdFlags, FileDesc}, + utils::{CreationFlags, StatusFlags}, + }, log_syscall_entry, prelude::*, + syscall::SYS_ACCEPT4, util::net::{get_socket_from_fd, write_socket_addr_to_user}, }; @@ -16,15 +20,68 @@ pub fn sys_accept( log_syscall_entry!(SYS_ACCEPT); debug!("sockfd = {sockfd}, sockaddr_ptr = 0x{sockaddr_ptr:x}, addrlen_ptr = 0x{addrlen_ptr:x}"); - let socket = get_socket_from_fd(sockfd)?; + let fd = do_accept(sockfd, sockaddr_ptr, addrlen_ptr, Flags::empty())?; + Ok(SyscallReturn::Return(fd as _)) +} - let (connected_socket, socket_addr) = socket.accept()?; - write_socket_addr_to_user(&socket_addr, sockaddr_ptr, addrlen_ptr)?; +pub fn sys_accept4( + sockfd: FileDesc, + sockaddr_ptr: Vaddr, + addrlen_ptr: Vaddr, + flags: u32, +) -> Result { + log_syscall_entry!(SYS_ACCEPT4); + trace!("raw flags = 0x{:x}", flags); + let flags = Flags::from_bits_truncate(flags); + debug!( + "sockfd = {}, sockaddr_ptr = 0x{:x}, addrlen_ptr = 0x{:x}, flags = {:?}", + sockfd, sockaddr_ptr, addrlen_ptr, flags + ); - let connected_fd = { + let fd = do_accept(sockfd, sockaddr_ptr, addrlen_ptr, flags)?; + Ok(SyscallReturn::Return(fd as _)) +} + +fn do_accept( + sockfd: FileDesc, + sockaddr_ptr: Vaddr, + addrlen_ptr: Vaddr, + flags: Flags, +) -> Result { + let (connected_socket, socket_addr) = { + let socket = get_socket_from_fd(sockfd)?; + socket.accept()? + }; + + if flags.contains(Flags::SOCK_NONBLOCK) { + connected_socket.set_status_flags(StatusFlags::O_NONBLOCK)?; + } + + let fd_flags = if flags.contains(Flags::SOCK_CLOEXEC) { + FdFlags::CLOEXEC + } else { + FdFlags::empty() + }; + + if sockaddr_ptr != 0 { + write_socket_addr_to_user(&socket_addr, sockaddr_ptr, addrlen_ptr)?; + } + + let fd = { let current = current!(); let mut file_table = current.file_table().lock(); - file_table.insert(connected_socket, FdFlags::empty()) + file_table.insert(connected_socket, fd_flags) }; - Ok(SyscallReturn::Return(connected_fd as _)) + + Ok(fd) } + +bitflags! { + struct Flags: u32 { + const SOCK_NONBLOCK = NONBLOCK; + const SOCK_CLOEXEC = CLOEXEC; + } +} + +const NONBLOCK: u32 = StatusFlags::O_NONBLOCK.bits(); +const CLOEXEC: u32 = CreationFlags::O_CLOEXEC.bits(); diff --git a/kernel/aster-nix/src/syscall/mod.rs b/kernel/aster-nix/src/syscall/mod.rs index 2739d4359..ff33e2c65 100644 --- a/kernel/aster-nix/src/syscall/mod.rs +++ b/kernel/aster-nix/src/syscall/mod.rs @@ -5,7 +5,7 @@ use aster_frame::cpu::UserContext; use self::{ - accept::sys_accept, + accept::{sys_accept, sys_accept4}, alarm::sys_alarm, bind::sys_bind, connect::sys_connect, @@ -391,6 +391,7 @@ define_syscall_nums!( SYS_UTIMENSAT = 280, SYS_EPOLL_PWAIT = 281, SYS_EVENTFD = 284, + SYS_ACCEPT4 = 288, SYS_EVENTFD2 = 290, SYS_EPOLL_CREATE1 = 291, SYS_PIPE2 = 293, @@ -584,6 +585,7 @@ pub fn syscall_dispatch( SYS_UTIMENSAT => syscall_handler!(4, sys_utimensat, args), SYS_EPOLL_PWAIT => syscall_handler!(5, sys_epoll_pwait, args), SYS_EVENTFD => syscall_handler!(1, sys_eventfd, args), + SYS_ACCEPT4 => syscall_handler!(4, sys_accept4, args), SYS_EVENTFD2 => syscall_handler!(2, sys_eventfd2, args), SYS_EPOLL_CREATE1 => syscall_handler!(1, sys_epoll_create1, args), SYS_PIPE2 => syscall_handler!(2, sys_pipe2, args),