diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 9f62758ff4..3e849fb0d3 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -3214,19 +3214,23 @@ ssize_t Process::sys$recvfrom(const Syscall::SC_recvfrom_params* user_params) return nrecv; } -int Process::sys$getsockname(int sockfd, sockaddr* addr, socklen_t* addrlen) +template +int Process::get_sock_or_peer_name(const Params& params) { - if (!validate_read_typed(addrlen)) + socklen_t addrlen_value; + if (!validate_read_and_copy_typed(&addrlen_value, params.addrlen)) return -EFAULT; - SmapDisabler disabler; - if (*addrlen <= 0) + if (addrlen_value <= 0) return -EINVAL; - if (!validate_write(addr, *addrlen)) + if (!validate_write(params.addr, addrlen_value)) return -EFAULT; - auto description = file_description(sockfd); + if (!validate_write_typed(params.addrlen)) + return -EFAULT; + + auto description = file_description(params.sockfd); if (!description) return -EBADF; @@ -3235,42 +3239,31 @@ int Process::sys$getsockname(int sockfd, sockaddr* addr, socklen_t* addrlen) auto& socket = *description->socket(); REQUIRE_PROMISE_FOR_SOCKET_DOMAIN(socket.domain()); - if (!socket.get_local_address(addr, addrlen)) - return -EINVAL; // FIXME: Should this be another error? I'm not sure. + u8 address_buffer[sizeof(sockaddr_un)]; + addrlen_value = min(sizeof(sockaddr_un), static_cast(addrlen_value)); + + if (!socket.get_local_address((sockaddr*)address_buffer, &addrlen_value)) + return -EINVAL; + + copy_to_user(params.addr, address_buffer, addrlen_value); return 0; } -int Process::sys$getpeername(int sockfd, sockaddr* addr, socklen_t* addrlen) +int Process::sys$getsockname(const Syscall::SC_getsockname_params* user_params) { - if (!validate_read_typed(addrlen)) + Syscall::SC_getsockname_params params; + if (!validate_read_and_copy_typed(¶ms, user_params)) return -EFAULT; + return get_sock_or_peer_name(params); +} - SmapDisabler disabler; - - if (*addrlen <= 0) - return -EINVAL; - - if (!validate_write(addr, *addrlen)) +int Process::sys$getpeername(const Syscall::SC_getpeername_params* user_params) +{ + Syscall::SC_getpeername_params params; + if (!validate_read_and_copy_typed(¶ms, user_params)) return -EFAULT; - - auto description = file_description(sockfd); - if (!description) - return -EBADF; - - if (!description->is_socket()) - return -ENOTSOCK; - - auto& socket = *description->socket(); - REQUIRE_PROMISE_FOR_SOCKET_DOMAIN(socket.domain()); - - if (socket.setup_state() != Socket::SetupState::Completed) - return -ENOTCONN; - - if (!socket.get_peer_address(addr, addrlen)) - return -EINVAL; // FIXME: Should this be another error? I'm not sure. - - return 0; + return get_sock_or_peer_name(params); } int Process::sys$sched_setparam(int tid, const struct sched_param* param) diff --git a/Kernel/Process.h b/Kernel/Process.h index cb27f0dc50..647c63cc80 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -263,8 +263,8 @@ public: ssize_t sys$recvfrom(const Syscall::SC_recvfrom_params*); int sys$getsockopt(const Syscall::SC_getsockopt_params*); int sys$setsockopt(const Syscall::SC_setsockopt_params*); - int sys$getsockname(int sockfd, sockaddr* addr, socklen_t* addrlen); - int sys$getpeername(int sockfd, sockaddr* addr, socklen_t* addrlen); + int sys$getsockname(const Syscall::SC_getsockname_params*); + int sys$getpeername(const Syscall::SC_getpeername_params*); int sys$sched_setparam(pid_t pid, const struct sched_param* param); int sys$sched_getparam(pid_t pid, struct sched_param* param); int sys$create_thread(void* (*)(void*), void* argument, const Syscall::SC_create_thread_params*); @@ -302,6 +302,9 @@ public: int sys$pledge(const Syscall::SC_pledge_params*); int sys$unveil(const Syscall::SC_unveil_params*); + template + int get_sock_or_peer_name(const Params&); + static void initialize(); [[noreturn]] void crash(int signal, u32 eip); diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index a66a795d94..a5541ab68c 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -297,6 +297,18 @@ struct SC_setsockopt_params { socklen_t value_size; }; +struct SC_getsockname_params { + int sockfd; + sockaddr* addr; + socklen_t* addrlen; +}; + +struct SC_getpeername_params { + int sockfd; + sockaddr* addr; + socklen_t* addrlen; +}; + struct SC_futex_params { i32* userspace_address; int futex_op;