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:
Andreas Kling 2020-01-27 21:11:36 +01:00
parent 7454926765
commit f4302b58fb
Notes: sideshowbarker 2024-07-19 09:46:27 +09:00
3 changed files with 44 additions and 36 deletions

View file

@ -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(&params, 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(&params, 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)

View file

@ -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);

View file

@ -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;