summaryrefslogtreecommitdiff
path: root/Kernel/Net/Socket.cpp
diff options
context:
space:
mode:
authorBrian Gianforcaro <b.gianfo@gmail.com>2020-08-07 02:29:05 -0700
committerAndreas Kling <kling@serenityos.org>2020-08-07 16:18:36 +0200
commit30b2c0dc85037c86d10ee14b46e4edfd42e785ec (patch)
tree601b0ec0510cabeb1c660313ad5489c80f965190 /Kernel/Net/Socket.cpp
parent6920d5f4230ebcd4f1d29dc5d9288cf79861906f (diff)
downloadserenity-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.cpp42
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: