diff options
author | Brian Gianforcaro <b.gianfo@gmail.com> | 2020-08-07 02:29:05 -0700 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-08-07 16:18:36 +0200 |
commit | 30b2c0dc85037c86d10ee14b46e4edfd42e785ec (patch) | |
tree | 601b0ec0510cabeb1c660313ad5489c80f965190 /Kernel/Net/Socket.cpp | |
parent | 6920d5f4230ebcd4f1d29dc5d9288cf79861906f (diff) | |
download | serenity-30b2c0dc85037c86d10ee14b46e4edfd42e785ec.zip |
Kernel: Use Userspace<T> for the getsockopt syscall and Socket interface
The way getsockopt is implemented for socket types requires us to push
down Userspace<T> using into those interfaces. This change does so, and
utilizes proper copy implementations instead of the kind of haphazard
pointer dereferencing that was occurring there before.
Diffstat (limited to 'Kernel/Net/Socket.cpp')
-rw-r--r-- | Kernel/Net/Socket.cpp | 42 |
1 files changed, 27 insertions, 15 deletions
diff --git a/Kernel/Net/Socket.cpp b/Kernel/Net/Socket.cpp index 1c303373fc..a021b80658 100644 --- a/Kernel/Net/Socket.cpp +++ b/Kernel/Net/Socket.cpp @@ -137,40 +137,52 @@ KResult Socket::setsockopt(int level, int option, Userspace<const void*> user_va } } -KResult Socket::getsockopt(FileDescription&, int level, int option, void* value, socklen_t* value_size) +KResult Socket::getsockopt(FileDescription&, int level, int option, Userspace<void*> value, Userspace<socklen_t*> value_size) { + socklen_t size; + if (!Process::current()->validate_read_and_copy_typed(&size, value_size)) + return KResult(-EFAULT); + ASSERT(level == SOL_SOCKET); switch (option) { case SO_SNDTIMEO: - if (*value_size < sizeof(timeval)) + if (size < sizeof(timeval)) return KResult(-EINVAL); - *(timeval*)value = m_send_timeout; - *value_size = sizeof(timeval); + copy_to_user(static_ptr_cast<timeval*>(value), &m_send_timeout); + size = sizeof(timeval); + copy_to_user(value_size, &size); return KSuccess; case SO_RCVTIMEO: - if (*value_size < sizeof(timeval)) + if (size < sizeof(timeval)) return KResult(-EINVAL); - *(timeval*)value = m_receive_timeout; - *value_size = sizeof(timeval); + copy_to_user(static_ptr_cast<timeval*>(value), &m_receive_timeout); + size = sizeof(timeval); + copy_to_user(value_size, &size); return KSuccess; - case SO_ERROR: - if (*value_size < sizeof(int)) + case SO_ERROR: { + if (size < sizeof(int)) return KResult(-EINVAL); dbg() << "getsockopt(SO_ERROR): FIXME!"; - *(int*)value = 0; - *value_size = sizeof(int); + int errno = 0; + copy_to_user(static_ptr_cast<int*>(value), &errno); + size = sizeof(int); + copy_to_user(value_size, &size); return KSuccess; + } case SO_BINDTODEVICE: - if (*value_size < IFNAMSIZ) + if (size < IFNAMSIZ) return KResult(-EINVAL); if (m_bound_interface) { const auto& name = m_bound_interface->name(); auto length = name.length() + 1; - memcpy(value, name.characters(), length); - *value_size = length; + copy_to_user(static_ptr_cast<char*>(value), name.characters(), length); + size = length; + copy_to_user(value_size, &size); return KSuccess; } else { - *value_size = 0; + size = 0; + copy_to_user(value_size, &size); + return KResult(-EFAULT); } default: |