Kernel: Remove SmapDisablers in sys$getsockname() and sys$getpeername()
Instead use the user/kernel copy helpers to only copy the minimum stuff needed from to/from userspace. Based on work started by Brian Gianforcaro.
This commit is contained in:
parent
7454926765
commit
f4302b58fb
Notes:
sideshowbarker
2024-07-19 09:46:27 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/f4302b58fb0
3 changed files with 44 additions and 36 deletions
|
@ -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<bool sockname, typename Params>
|
||||
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<size_t>(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<true>(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<false>(params);
|
||||
}
|
||||
|
||||
int Process::sys$sched_setparam(int tid, const struct sched_param* param)
|
||||
|
|
|
@ -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<bool sockname, typename Params>
|
||||
int get_sock_or_peer_name(const Params&);
|
||||
|
||||
static void initialize();
|
||||
|
||||
[[noreturn]] void crash(int signal, u32 eip);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue