Bläddra i källkod

Kernel: Use copy_typed_from_user() in more places :^)

Andreas Kling 3 år sedan
förälder
incheckning
abf2204402

+ 1 - 2
Kernel/FileSystem/Inode.cpp

@@ -318,8 +318,7 @@ ErrorOr<void> Inode::can_apply_flock(OpenFileDescription const& description, flo
 
 ErrorOr<void> Inode::apply_flock(Process const& process, OpenFileDescription const& description, Userspace<flock const*> input_lock)
 {
-    flock new_lock = {};
-    TRY(copy_from_user(&new_lock, input_lock));
+    auto new_lock = TRY(copy_typed_from_user(input_lock));
     TRY(normalize_flock(description, new_lock));
 
     MutexLocker locker(m_inode_lock);

+ 8 - 13
Kernel/Graphics/GenericFramebufferDevice.cpp

@@ -61,9 +61,8 @@ ErrorOr<void> GenericFramebufferDevice::ioctl(OpenFileDescription&, unsigned req
         return copy_to_user(user_head_properties, &head_properties);
     }
     case FB_IOCTL_SET_HEAD_RESOLUTION: {
-        auto user_head_resolution = static_ptr_cast<FBHeadResolution*>(arg);
-        FBHeadResolution head_resolution;
-        TRY(copy_from_user(&head_resolution, user_head_resolution));
+        auto user_head_resolution = static_ptr_cast<FBHeadResolution const*>(arg);
+        auto head_resolution = TRY(copy_typed_from_user(user_head_resolution));
         TRY(verify_head_index(head_resolution.head_index));
 
         if (head_resolution.pitch < 0)
@@ -76,9 +75,8 @@ ErrorOr<void> GenericFramebufferDevice::ioctl(OpenFileDescription&, unsigned req
         return {};
     }
     case FB_IOCTL_SET_HEAD_VERTICAL_OFFSET_BUFFER: {
-        auto user_head_vertical_buffer_offset = static_ptr_cast<FBHeadVerticalOffset*>(arg);
-        FBHeadVerticalOffset head_vertical_buffer_offset;
-        TRY(copy_from_user(&head_vertical_buffer_offset, user_head_vertical_buffer_offset));
+        auto user_head_vertical_buffer_offset = static_ptr_cast<FBHeadVerticalOffset const*>(arg);
+        auto head_vertical_buffer_offset = TRY(copy_typed_from_user(user_head_vertical_buffer_offset));
         TRY(verify_head_index(head_vertical_buffer_offset.head_index));
 
         if (head_vertical_buffer_offset.offsetted < 0 || head_vertical_buffer_offset.offsetted > 1)
@@ -98,9 +96,8 @@ ErrorOr<void> GenericFramebufferDevice::ioctl(OpenFileDescription&, unsigned req
     case FB_IOCTL_FLUSH_HEAD_BUFFERS: {
         if (!partial_flushing_support())
             return Error::from_errno(ENOTSUP);
-        auto user_flush_rects = static_ptr_cast<FBFlushRects*>(arg);
-        FBFlushRects flush_rects;
-        TRY(copy_from_user(&flush_rects, user_flush_rects));
+        auto user_flush_rects = static_ptr_cast<FBFlushRects const*>(arg);
+        auto flush_rects = TRY(copy_typed_from_user(user_flush_rects));
         if (Checked<unsigned>::multiplication_would_overflow(flush_rects.count, sizeof(FBRect)))
             return Error::from_errno(EFAULT);
         MutexLocker locker(m_flushing_lock);
@@ -117,11 +114,9 @@ ErrorOr<void> GenericFramebufferDevice::ioctl(OpenFileDescription&, unsigned req
         if (!flushing_support())
             return Error::from_errno(ENOTSUP);
         // Note: We accept a FBRect, but we only really care about the head_index value.
-        auto user_rect = static_ptr_cast<FBRect*>(arg);
-        FBRect rect;
-        TRY(copy_from_user(&rect, user_rect));
+        auto user_rect = static_ptr_cast<FBRect const*>(arg);
+        auto rect = TRY(copy_typed_from_user(user_rect));
         TRY(verify_head_index(rect.head_index));
-
         TRY(flush_head_buffer(rect.head_index));
         return {};
     }

+ 4 - 10
Kernel/Net/Socket.cpp

@@ -112,23 +112,17 @@ ErrorOr<void> Socket::setsockopt(int level, int option, Userspace<const void*> u
     case SO_TIMESTAMP:
         if (user_value_size != sizeof(int))
             return EINVAL;
-        {
-            int timestamp;
-            TRY(copy_from_user(&timestamp, static_ptr_cast<const int*>(user_value)));
-            m_timestamp = timestamp;
-        }
-        if (m_timestamp && (domain() != AF_INET || type() == SOCK_STREAM)) {
+        m_timestamp = TRY(copy_typed_from_user(static_ptr_cast<int const*>(user_value)));
+        if (m_timestamp != 0 && (domain() != AF_INET || type() == SOCK_STREAM)) {
             // FIXME: Support SO_TIMESTAMP for more protocols?
             m_timestamp = 0;
             return ENOTSUP;
         }
         return {};
     case SO_DONTROUTE: {
-        int routing_disabled;
-        if (user_value_size != sizeof(routing_disabled))
+        if (user_value_size != sizeof(int))
             return EINVAL;
-        TRY(copy_from_user(&routing_disabled, static_ptr_cast<const int*>(user_value)));
-        m_routing_disabled = routing_disabled != 0;
+        m_routing_disabled = TRY(copy_typed_from_user(static_ptr_cast<int const*>(user_value))) != 0;
         return {};
     }
     default:

+ 1 - 3
Kernel/Syscalls/ioctl.cpp

@@ -16,9 +16,7 @@ ErrorOr<FlatPtr> Process::sys$ioctl(int fd, unsigned request, FlatPtr arg)
     VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
     auto description = TRY(fds().open_file_description(fd));
     if (request == FIONBIO) {
-        int non_blocking;
-        TRY(copy_from_user(&non_blocking, Userspace<const int*>(arg)));
-        description->set_blocking(non_blocking == 0);
+        description->set_blocking(TRY(copy_typed_from_user(Userspace<int const*>(arg))) == 0);
         return 0;
     }
     TRY(description->file().ioctl(*description, request, arg));

+ 1 - 3
Kernel/Syscalls/ptrace.cpp

@@ -180,9 +180,7 @@ ErrorOr<FlatPtr> Process::peek_user_data(Userspace<const FlatPtr*> address)
     // This function can be called from the context of another
     // process that called PT_PEEK
     ScopedAddressSpaceSwitcher switcher(*this);
-    FlatPtr data;
-    TRY(copy_from_user(&data, address));
-    return data;
+    return TRY(copy_typed_from_user(address));
 }
 
 ErrorOr<void> Process::peek_user_data(Span<u8> destination, Userspace<const u8*> address)

+ 3 - 4
Kernel/Syscalls/sched.cpp

@@ -20,10 +20,9 @@ ErrorOr<FlatPtr> Process::sys$sched_setparam(int pid, Userspace<const struct sch
 {
     VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
     REQUIRE_PROMISE(proc);
-    struct sched_param desired_param;
-    TRY(copy_from_user(&desired_param, user_param));
+    auto param = TRY(copy_typed_from_user(user_param));
 
-    if (desired_param.sched_priority < THREAD_PRIORITY_MIN || desired_param.sched_priority > THREAD_PRIORITY_MAX)
+    if (param.sched_priority < THREAD_PRIORITY_MIN || param.sched_priority > THREAD_PRIORITY_MAX)
         return EINVAL;
 
     auto* peer = Thread::current();
@@ -37,7 +36,7 @@ ErrorOr<FlatPtr> Process::sys$sched_setparam(int pid, Userspace<const struct sch
     if (!is_superuser() && euid() != peer->process().uid() && uid() != peer->process().uid())
         return EPERM;
 
-    peer->set_priority((u32)desired_param.sched_priority);
+    peer->set_priority((u32)param.sched_priority);
     return 0;
 }
 

+ 14 - 17
Kernel/Syscalls/sigaction.cpp

@@ -18,8 +18,7 @@ ErrorOr<FlatPtr> Process::sys$sigprocmask(int how, Userspace<const sigset_t*> se
     auto current_thread = Thread::current();
     u32 previous_signal_mask;
     if (set) {
-        sigset_t set_value;
-        TRY(copy_from_user(&set_value, set));
+        auto set_value = TRY(copy_typed_from_user(set));
         switch (how) {
         case SIG_BLOCK:
             previous_signal_mask = current_thread->signal_mask_block(set_value, true);
@@ -67,8 +66,7 @@ ErrorOr<FlatPtr> Process::sys$sigaction(int signum, Userspace<const sigaction*>
         TRY(copy_to_user(user_old_act, &old_act));
     }
     if (user_act) {
-        sigaction act {};
-        TRY(copy_from_user(&act, user_act));
+        auto act = TRY(copy_typed_from_user(user_act));
         action.flags = act.sa_flags;
         action.handler_or_sigaction = VirtualAddress { reinterpret_cast<void*>(act.sa_sigaction) };
     }
@@ -258,12 +256,12 @@ ErrorOr<void> Process::remap_range_as_stack(FlatPtr address, size_t size)
     return EINVAL;
 }
 
-ErrorOr<FlatPtr> Process::sys$sigaltstack(Userspace<const stack_t*> ss, Userspace<stack_t*> old_ss)
+ErrorOr<FlatPtr> Process::sys$sigaltstack(Userspace<const stack_t*> user_ss, Userspace<stack_t*> user_old_ss)
 {
     VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
     REQUIRE_PROMISE(sigaction);
 
-    if (old_ss) {
+    if (user_old_ss) {
         stack_t old_ss_value;
         old_ss_value.ss_sp = (void*)Thread::current()->m_alternative_signal_stack;
         old_ss_value.ss_size = Thread::current()->m_alternative_signal_stack_size;
@@ -272,33 +270,32 @@ ErrorOr<FlatPtr> Process::sys$sigaltstack(Userspace<const stack_t*> ss, Userspac
             old_ss_value.ss_flags = SS_DISABLE;
         else if (Thread::current()->is_in_alternative_signal_stack())
             old_ss_value.ss_flags = SS_ONSTACK;
-        TRY(copy_to_user(old_ss, &old_ss_value));
+        TRY(copy_to_user(user_old_ss, &old_ss_value));
     }
 
-    if (ss) {
-        stack_t ss_value;
-        TRY(copy_from_user(&ss_value, ss));
+    if (user_ss) {
+        auto ss = TRY(copy_typed_from_user(user_ss));
 
         if (Thread::current()->is_in_alternative_signal_stack())
             return EPERM;
 
-        if (ss_value.ss_flags == SS_DISABLE) {
+        if (ss.ss_flags == SS_DISABLE) {
             Thread::current()->m_alternative_signal_stack_size = 0;
             Thread::current()->m_alternative_signal_stack = 0;
-        } else if (ss_value.ss_flags == 0) {
-            if (ss_value.ss_size <= MINSIGSTKSZ)
+        } else if (ss.ss_flags == 0) {
+            if (ss.ss_size <= MINSIGSTKSZ)
                 return ENOMEM;
-            if (Checked<FlatPtr>::addition_would_overflow((FlatPtr)ss_value.ss_sp, ss_value.ss_size))
+            if (Checked<FlatPtr>::addition_would_overflow((FlatPtr)ss.ss_sp, ss.ss_size))
                 return ENOMEM;
 
             // In order to preserve compatibility with our MAP_STACK, W^X and syscall region
             // protections, sigaltstack ranges are carved out of their regions, zeroed, and
             // turned into read/writable MAP_STACK-enabled regions.
             // This is inspired by OpenBSD's solution: https://man.openbsd.org/sigaltstack.2
-            TRY(remap_range_as_stack((FlatPtr)ss_value.ss_sp, ss_value.ss_size));
+            TRY(remap_range_as_stack((FlatPtr)ss.ss_sp, ss.ss_size));
 
-            Thread::current()->m_alternative_signal_stack = (FlatPtr)ss_value.ss_sp;
-            Thread::current()->m_alternative_signal_stack_size = ss_value.ss_size;
+            Thread::current()->m_alternative_signal_stack = (FlatPtr)ss.ss_sp;
+            Thread::current()->m_alternative_signal_stack_size = ss.ss_size;
         } else {
             return EINVAL;
         }

+ 1 - 2
Kernel/Syscalls/socket.cpp

@@ -162,8 +162,7 @@ ErrorOr<FlatPtr> Process::sys$sendmsg(int sockfd, Userspace<const struct msghdr*
 {
     VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
     REQUIRE_PROMISE(stdio);
-    struct msghdr msg = {};
-    TRY(copy_from_user(&msg, user_msg));
+    auto msg = TRY(copy_typed_from_user(user_msg));
 
     if (msg.msg_iovlen != 1)
         return ENOTSUP; // FIXME: Support this :)

+ 8 - 12
Kernel/TTY/TTY.cpp

@@ -476,9 +476,6 @@ ErrorOr<void> TTY::ioctl(OpenFileDescription&, unsigned request, Userspace<void*
 {
     REQUIRE_PROMISE(tty);
     auto& current_process = Process::current();
-    Userspace<termios*> user_termios;
-    Userspace<winsize*> user_winsize;
-
 #if 0
     // FIXME: When should we block things?
     //        How do we make this work together with MasterPTY forwarding to us?
@@ -521,15 +518,14 @@ ErrorOr<void> TTY::ioctl(OpenFileDescription&, unsigned request, Userspace<void*
         return {};
     }
     case TCGETS: {
-        user_termios = static_ptr_cast<termios*>(arg);
+        auto user_termios = static_ptr_cast<termios*>(arg);
         return copy_to_user(user_termios, &m_termios);
     }
     case TCSETS:
     case TCSETSF:
     case TCSETSW: {
-        user_termios = static_ptr_cast<termios*>(arg);
-        termios termios;
-        TRY(copy_from_user(&termios, user_termios));
+        auto user_termios = static_ptr_cast<termios const*>(arg);
+        auto termios = TRY(copy_typed_from_user(user_termios));
         auto rc = set_termios(termios);
         if (request == TCSETSF)
             flush_input();
@@ -545,18 +541,18 @@ ErrorOr<void> TTY::ioctl(OpenFileDescription&, unsigned request, Userspace<void*
         }
         return {};
     }
-    case TIOCGWINSZ:
-        user_winsize = static_ptr_cast<winsize*>(arg);
+    case TIOCGWINSZ: {
+        auto user_winsize = static_ptr_cast<winsize*>(arg);
         winsize ws;
         ws.ws_row = m_rows;
         ws.ws_col = m_columns;
         ws.ws_xpixel = 0;
         ws.ws_ypixel = 0;
         return copy_to_user(user_winsize, &ws);
+    }
     case TIOCSWINSZ: {
-        user_winsize = static_ptr_cast<winsize*>(arg);
-        winsize ws;
-        TRY(copy_from_user(&ws, user_winsize));
+        auto user_winsize = static_ptr_cast<winsize const*>(arg);
+        auto ws = TRY(copy_typed_from_user(user_winsize));
         if (ws.ws_col == m_columns && ws.ws_row == m_rows)
             return {};
         m_rows = ws.ws_row;