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

This commit is contained in:
Andreas Kling 2021-12-17 09:12:20 +01:00
parent 39d9337db5
commit abf2204402
9 changed files with 41 additions and 66 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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