mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-29 19:10:26 +00:00
Kernel: Sanitize all user-supplied timeval's/timespec's
This also removes a bunch of unnecessary EINVAL. Most of them weren't even recommended by POSIX.
This commit is contained in:
parent
649abc01bc
commit
8598240193
Notes:
sideshowbarker
2024-07-18 21:48:10 +09:00
Author: https://github.com/BenWiederhake Commit: https://github.com/SerenityOS/serenity/commit/85982401939 Pull-request: https://github.com/SerenityOS/serenity/pull/5323 Reviewed-by: https://github.com/ADKaster Reviewed-by: https://github.com/awesomekling Reviewed-by: https://github.com/bgianfo
4 changed files with 42 additions and 28 deletions
|
@ -106,14 +106,24 @@ KResult Socket::setsockopt(int level, int option, Userspace<const void*> user_va
|
|||
case SO_SNDTIMEO:
|
||||
if (user_value_size != sizeof(timeval))
|
||||
return EINVAL;
|
||||
if (!copy_from_user(&m_send_timeout, static_ptr_cast<const timeval*>(user_value)))
|
||||
{
|
||||
auto timeout = copy_time_from_user(static_ptr_cast<const timeval*>(user_value));
|
||||
if (!timeout.has_value())
|
||||
return EFAULT;
|
||||
// FIXME: Should use AK::Time internally
|
||||
m_send_timeout = timeout->to_timeval();
|
||||
}
|
||||
return KSuccess;
|
||||
case SO_RCVTIMEO:
|
||||
if (user_value_size != sizeof(timeval))
|
||||
return EINVAL;
|
||||
if (!copy_from_user(&m_receive_timeout, static_ptr_cast<const timeval*>(user_value)))
|
||||
{
|
||||
auto timeout = copy_time_from_user(static_ptr_cast<const timeval*>(user_value));
|
||||
if (!timeout.has_value())
|
||||
return EFAULT;
|
||||
// FIXME: Should use AK::Time internally
|
||||
m_receive_timeout = timeout->to_timeval();
|
||||
}
|
||||
return KSuccess;
|
||||
case SO_BINDTODEVICE: {
|
||||
if (user_value_size != IFNAMSIZ)
|
||||
|
|
|
@ -50,13 +50,14 @@ KResultOr<int> Process::sys$clock_settime(clockid_t clock_id, Userspace<const ti
|
|||
if (!is_superuser())
|
||||
return EPERM;
|
||||
|
||||
timespec ts;
|
||||
if (!copy_from_user(&ts, user_ts))
|
||||
auto ts = copy_time_from_user(user_ts);
|
||||
if (!ts.has_value())
|
||||
return EFAULT;
|
||||
|
||||
switch (clock_id) {
|
||||
case CLOCK_REALTIME:
|
||||
TimeManagement::the().set_epoch_time(ts);
|
||||
// FIXME: Should use AK::Time internally
|
||||
TimeManagement::the().set_epoch_time(ts->to_timespec());
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
|
@ -72,9 +73,9 @@ KResultOr<int> Process::sys$clock_nanosleep(Userspace<const Syscall::SC_clock_na
|
|||
if (!copy_from_user(¶ms, user_params))
|
||||
return EFAULT;
|
||||
|
||||
timespec requested_sleep;
|
||||
if (!copy_from_user(&requested_sleep, params.requested_sleep))
|
||||
return EFAULT;
|
||||
Optional<Time> requested_sleep = copy_time_from_user(params.requested_sleep);
|
||||
if (!requested_sleep.has_value())
|
||||
return -EFAULT;
|
||||
|
||||
bool is_absolute;
|
||||
switch (params.flags) {
|
||||
|
@ -93,10 +94,12 @@ KResultOr<int> Process::sys$clock_nanosleep(Userspace<const Syscall::SC_clock_na
|
|||
|
||||
bool was_interrupted;
|
||||
if (is_absolute) {
|
||||
was_interrupted = Thread::current()->sleep_until(params.clock_id, requested_sleep).was_interrupted();
|
||||
// FIXME: Should use AK::Time internally
|
||||
was_interrupted = Thread::current()->sleep_until(params.clock_id, requested_sleep->to_timespec()).was_interrupted();
|
||||
} else {
|
||||
timespec remaining_sleep;
|
||||
was_interrupted = Thread::current()->sleep(params.clock_id, requested_sleep, &remaining_sleep).was_interrupted();
|
||||
// FIXME: Should use AK::Time internally
|
||||
was_interrupted = Thread::current()->sleep(params.clock_id, requested_sleep->to_timespec(), &remaining_sleep).was_interrupted();
|
||||
if (was_interrupted && params.remaining_sleep && !copy_to_user(params.remaining_sleep, &remaining_sleep))
|
||||
return EFAULT;
|
||||
}
|
||||
|
@ -119,16 +122,12 @@ KResultOr<int> Process::sys$adjtime(Userspace<const timeval*> user_delta, Usersp
|
|||
REQUIRE_PROMISE(settime);
|
||||
if (!is_superuser())
|
||||
return EPERM;
|
||||
timeval delta;
|
||||
if (!copy_from_user(&delta, user_delta))
|
||||
auto delta = copy_time_from_user(user_delta);
|
||||
if (!delta.has_value())
|
||||
return EFAULT;
|
||||
|
||||
if (delta.tv_usec < 0 || delta.tv_usec >= 1'000'000)
|
||||
return EINVAL;
|
||||
|
||||
timespec delta_ts;
|
||||
timeval_to_timespec(delta, delta_ts);
|
||||
TimeManagement::the().set_remaining_epoch_time_adjustment(delta_ts);
|
||||
// FIXME: Should use AK::Time internally
|
||||
TimeManagement::the().set_remaining_epoch_time_adjustment(delta->to_timespec());
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -118,12 +118,14 @@ KResultOr<int> Process::sys$futex(Userspace<const Syscall::SC_futex_params*> use
|
|||
case FUTEX_REQUEUE:
|
||||
case FUTEX_CMP_REQUEUE: {
|
||||
if (params.timeout) {
|
||||
timespec ts_stimeout { 0, 0 };
|
||||
if (!copy_from_user(&ts_stimeout, params.timeout))
|
||||
auto timeout_time = copy_time_from_user(params.timeout);
|
||||
if (!timeout_time.has_value())
|
||||
return EFAULT;
|
||||
clockid_t clock_id = (params.futex_op & FUTEX_CLOCK_REALTIME) ? CLOCK_REALTIME_COARSE : CLOCK_MONOTONIC_COARSE;
|
||||
bool is_absolute = cmd != FUTEX_WAIT;
|
||||
timeout = Thread::BlockTimeout(is_absolute, &ts_stimeout, nullptr, clock_id);
|
||||
// FIXME: Should use AK::Time internally
|
||||
timespec timeout_copy = timeout_time->to_timespec();
|
||||
timeout = Thread::BlockTimeout(is_absolute, &timeout_copy, nullptr, clock_id);
|
||||
}
|
||||
if (cmd == FUTEX_WAIT_BITSET && params.val3 == FUTEX_BITSET_MATCH_ANY)
|
||||
cmd = FUTEX_WAIT;
|
||||
|
|
|
@ -45,9 +45,11 @@ KResultOr<int> Process::sys$select(Userspace<const Syscall::SC_select_params*> u
|
|||
|
||||
Thread::BlockTimeout timeout;
|
||||
if (params.timeout) {
|
||||
timespec timeout_copy;
|
||||
if (!copy_from_user(&timeout_copy, params.timeout))
|
||||
Optional<Time> timeout_time = copy_time_from_user(params.timeout);
|
||||
if (!timeout_time.has_value())
|
||||
return EFAULT;
|
||||
auto timeout_copy = timeout_time->to_timespec();
|
||||
// FIXME: Should use AK::Time internally
|
||||
timeout = Thread::BlockTimeout(false, &timeout_copy);
|
||||
}
|
||||
|
||||
|
@ -142,7 +144,6 @@ KResultOr<int> Process::sys$poll(Userspace<const Syscall::SC_poll_params*> user_
|
|||
{
|
||||
REQUIRE_PROMISE(stdio);
|
||||
|
||||
// FIXME: Return -EINVAL if timeout is invalid.
|
||||
Syscall::SC_poll_params params;
|
||||
if (!copy_from_user(¶ms, user_params))
|
||||
return EFAULT;
|
||||
|
@ -152,9 +153,11 @@ KResultOr<int> Process::sys$poll(Userspace<const Syscall::SC_poll_params*> user_
|
|||
|
||||
Thread::BlockTimeout timeout;
|
||||
if (params.timeout) {
|
||||
timespec timeout_copy;
|
||||
if (!copy_from_user(&timeout_copy, params.timeout))
|
||||
auto timeout_time = copy_time_from_user(params.timeout);
|
||||
if (!timeout_time.has_value())
|
||||
return EFAULT;
|
||||
timespec timeout_copy = timeout_time->to_timespec();
|
||||
// FIXME: Should use AK::Time internally
|
||||
timeout = Thread::BlockTimeout(false, &timeout_copy);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue