summaryrefslogtreecommitdiff
path: root/Kernel/Net
diff options
context:
space:
mode:
authorBen Wiederhake <BenWiederhake.GitHub@gmx.de>2021-02-21 20:03:44 +0100
committerAndreas Kling <kling@serenityos.org>2021-03-02 08:36:08 +0100
commitb374dd03bdcd6608dbf8ed0b5ef4af3b2bf3845c (patch)
treee26356e4a0460a310891a335734407ed34a6aa58 /Kernel/Net
parentb7c5d977c724c893d077a16648a0a0ea7fe061fc (diff)
downloadserenity-b374dd03bdcd6608dbf8ed0b5ef4af3b2bf3845c.zip
Kernel: Prevent inconsistent state after invalid read
copy_from_user can fail, for example when the user-supplied pointer is just before the end of mapped address space. In that case, the first few bytes would get copied, permanently overwriting the internal state of the Socket, potentially leaving it in an inconsistent or at least difficult-to-predict state.
Diffstat (limited to 'Kernel/Net')
-rw-r--r--Kernel/Net/Socket.cpp8
1 files changed, 6 insertions, 2 deletions
diff --git a/Kernel/Net/Socket.cpp b/Kernel/Net/Socket.cpp
index aeacd3b1fd..a51e092a2a 100644
--- a/Kernel/Net/Socket.cpp
+++ b/Kernel/Net/Socket.cpp
@@ -134,8 +134,12 @@ KResult Socket::setsockopt(int level, int option, Userspace<const void*> user_va
case SO_TIMESTAMP:
if (user_value_size != sizeof(int))
return EINVAL;
- if (!copy_from_user(&m_timestamp, static_ptr_cast<const int*>(user_value)))
- return EFAULT;
+ {
+ int timestamp;
+ if (!copy_from_user(&timestamp, static_ptr_cast<const int*>(user_value)))
+ return EFAULT;
+ m_timestamp = timestamp;
+ }
if (m_timestamp && (domain() != AF_INET || type() == SOCK_STREAM)) {
// FIXME: Support SO_TIMESTAMP for more protocols?
m_timestamp = 0;