1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 17:47:44 +00:00

Kernel: Utilize AK::Userspace<T> in the ioctl interface

It's easy to forget the responsibility of validating and safely copying
kernel parameters in code that is far away from syscalls. ioctl's are
one such example, and bugs there are just as dangerous as at the root
syscall level.

To avoid this case, utilize the AK::Userspace<T> template in the ioctl
kernel interface so that implementors have no choice but to properly
validate and copy ioctl pointer arguments.
This commit is contained in:
Brian Gianforcaro 2021-07-26 02:47:00 -07:00 committed by Ali Mohammad Pur
parent 0bb3d83a48
commit 9a04f53a0f
16 changed files with 99 additions and 93 deletions

View file

@ -106,7 +106,7 @@ KResult MasterPTY::close()
return KSuccess;
}
int MasterPTY::ioctl(FileDescription& description, unsigned request, FlatPtr arg)
int MasterPTY::ioctl(FileDescription& description, unsigned request, Userspace<void*> arg)
{
REQUIRE_PROMISE(tty);
if (!m_slave)

View file

@ -40,7 +40,7 @@ private:
virtual bool can_write(const FileDescription&, size_t) const override;
virtual KResult close() override;
virtual bool is_master_pty() const override { return true; }
virtual int ioctl(FileDescription&, unsigned request, FlatPtr arg) override;
virtual int ioctl(FileDescription&, unsigned request, Userspace<void*> arg) override;
virtual StringView class_name() const override { return "MasterPTY"; }
RefPtr<SlavePTY> m_slave;

View file

@ -454,12 +454,12 @@ int TTY::set_termios(const termios& t)
return rc;
}
int TTY::ioctl(FileDescription&, unsigned request, FlatPtr arg)
int TTY::ioctl(FileDescription&, unsigned request, Userspace<void*> arg)
{
REQUIRE_PROMISE(tty);
auto& current_process = *Process::current();
termios* user_termios;
winsize* user_winsize;
Userspace<termios*> user_termios;
Userspace<winsize*> user_winsize;
#if 0
// FIXME: When should we block things?
@ -472,7 +472,7 @@ int TTY::ioctl(FileDescription&, unsigned request, FlatPtr arg)
case TIOCGPGRP:
return this->pgid().value();
case TIOCSPGRP: {
ProcessGroupID pgid = static_cast<pid_t>(arg);
ProcessGroupID pgid = static_cast<pid_t>(arg.ptr());
if (pgid <= 0)
return -EINVAL;
InterruptDisabler disabler;
@ -500,7 +500,7 @@ int TTY::ioctl(FileDescription&, unsigned request, FlatPtr arg)
return 0;
}
case TCGETS: {
user_termios = reinterpret_cast<termios*>(arg);
user_termios = static_ptr_cast<termios*>(arg);
if (!copy_to_user(user_termios, &m_termios))
return -EFAULT;
return 0;
@ -508,7 +508,7 @@ int TTY::ioctl(FileDescription&, unsigned request, FlatPtr arg)
case TCSETS:
case TCSETSF:
case TCSETSW: {
user_termios = reinterpret_cast<termios*>(arg);
user_termios = static_ptr_cast<termios*>(arg);
termios termios;
if (!copy_from_user(&termios, user_termios))
return -EFAULT;
@ -517,16 +517,18 @@ int TTY::ioctl(FileDescription&, unsigned request, FlatPtr arg)
flush_input();
return rc;
}
case TCFLSH:
case TCFLSH: {
// Serenity's TTY implementation does not use an output buffer, so ignore TCOFLUSH.
if (arg == TCIFLUSH || arg == TCIOFLUSH) {
auto operation = static_cast<u8>(arg.ptr());
if (operation == TCIFLUSH || operation == TCIOFLUSH) {
flush_input();
} else if (arg != TCOFLUSH) {
} else if (operation != TCOFLUSH) {
return -EINVAL;
}
return 0;
}
case TIOCGWINSZ:
user_winsize = reinterpret_cast<winsize*>(arg);
user_winsize = static_ptr_cast<winsize*>(arg);
winsize ws;
ws.ws_row = m_rows;
ws.ws_col = m_columns;
@ -536,7 +538,7 @@ int TTY::ioctl(FileDescription&, unsigned request, FlatPtr arg)
return -EFAULT;
return 0;
case TIOCSWINSZ: {
user_winsize = reinterpret_cast<winsize*>(arg);
user_winsize = static_ptr_cast<winsize*>(arg);
winsize ws;
if (!copy_from_user(&ws, user_winsize))
return -EFAULT;

View file

@ -25,7 +25,7 @@ public:
virtual KResultOr<size_t> write(FileDescription&, u64, const UserOrKernelBuffer&, size_t) override;
virtual bool can_read(const FileDescription&, size_t) const override;
virtual bool can_write(const FileDescription&, size_t) const override;
virtual int ioctl(FileDescription&, unsigned request, FlatPtr arg) override final;
virtual int ioctl(FileDescription&, unsigned request, Userspace<void*> arg) override final;
virtual String absolute_path(const FileDescription&) const override { return tty_name(); }
virtual String const& tty_name() const = 0;