diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 5915872b30..7019881b4a 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -21,7 +21,6 @@ //#define DEBUG_IO //#define TASK_DEBUG //#define FORK_DEBUG -#define TERMIOS_DEBUG #define SIGNAL_DEBUG #define MAX_PROCESS_GIDS 32 @@ -1467,6 +1466,24 @@ bool Process::isValidAddressForKernel(LinearAddress laddr) const return validate_user_read(laddr); } +bool Process::validate_read(void* address, size_t size) const +{ + if ((reinterpret_cast(address) & PAGE_MASK) != ((reinterpret_cast(address) + size) & PAGE_MASK)) { + if (!MM.validate_user_read(*this, LinearAddress((dword)address).offset(size))) + return false; + } + return MM.validate_user_read(*this, LinearAddress((dword)address)); +} + +bool Process::validate_write(void* address, size_t size) const +{ + if ((reinterpret_cast(address) & PAGE_MASK) != ((reinterpret_cast(address) + size) & PAGE_MASK)) { + if (!MM.validate_user_write(*this, LinearAddress((dword)address).offset(size))) + return false; + } + return MM.validate_user_write(*this, LinearAddress((dword)address)); +} + bool Process::validate_user_read(LinearAddress laddr) const { InterruptDisabler disabler; @@ -1553,39 +1570,6 @@ int Process::sys$setpgid(pid_t specified_pid, pid_t specified_pgid) return 0; } -int Process::sys$tcgetattr(int fd, Unix::termios* tp) -{ - VALIDATE_USER_WRITE(tp, sizeof(Unix::termios)); - auto* descriptor = file_descriptor(fd); - if (!descriptor) - return -EBADF; - if (!descriptor->isTTY()) - return -ENOTTY; -#ifdef TERMIOS_DEBUG - dbgprintf("sys$tcgetattr(fd=%d, tp=%p)\n", fd, tp); -#endif - auto& tty = *descriptor->tty(); - memcpy(tp, &tty.termios(), sizeof(Unix::termios)); - return 0; -} - -int Process::sys$tcsetattr(int fd, int optional_actions, const Unix::termios* tp) -{ - (void) optional_actions; - VALIDATE_USER_READ(tp, sizeof(Unix::termios)); - auto* descriptor = file_descriptor(fd); - if (!descriptor) - return -EBADF; - if (!descriptor->isTTY()) - return -ENOTTY; -#ifdef TERMIOS_DEBUG - dbgprintf("sys$tcsetattr(fd=%d, tp=%p)\n", fd, tp); -#endif - auto& tty = *descriptor->tty(); - tty.set_termios(*tp); - return 0; -} - int Process::sys$ioctl(int fd, unsigned request, unsigned arg) { auto* descriptor = file_descriptor(fd); diff --git a/Kernel/Process.h b/Kernel/Process.h index f15afd1ae9..19cdf6a65f 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -199,6 +199,9 @@ public: bool validate_user_read(LinearAddress) const; bool validate_user_write(LinearAddress) const; + bool validate_read(void*, size_t) const; + bool validate_write(void*, size_t) const; + CoreInode* cwd_inode() { return m_cwd ? m_cwd->core_inode() : nullptr; } CoreInode* executable_inode() { return m_executable ? m_executable->core_inode() : nullptr; } diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index 95f41e0c82..8469ef7c87 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -171,10 +171,6 @@ static DWORD handle(RegisterDump& regs, DWORD function, DWORD arg1, DWORD arg2, return current->sys$access((const char*)arg1, (int)arg2); case Syscall::SC_fcntl: return current->sys$fcntl((int)arg1, (int)arg2, (dword)arg3); - case Syscall::SC_tcgetattr: - return current->sys$tcgetattr((int)arg1, (Unix::termios*)arg2); - case Syscall::SC_tcsetattr: - return current->sys$tcsetattr((int)arg1, (int)arg2, (const Unix::termios*)arg3); case Syscall::SC_ioctl: return current->sys$ioctl((int)arg1, (unsigned)arg2, (unsigned)arg3); default: diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index 65ce348950..548bd4d1c8 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -62,8 +62,6 @@ __ENUMERATE_SYSCALL(fstat) \ __ENUMERATE_SYSCALL(access) \ __ENUMERATE_SYSCALL(fcntl) \ - __ENUMERATE_SYSCALL(tcsetattr) \ - __ENUMERATE_SYSCALL(tcgetattr) \ __ENUMERATE_SYSCALL(ioctl) \ diff --git a/Kernel/TTY.cpp b/Kernel/TTY.cpp index 6b2f2fb34c..754bef3f52 100644 --- a/Kernel/TTY.cpp +++ b/Kernel/TTY.cpp @@ -71,19 +71,34 @@ void TTY::set_termios(const Unix::termios& t) int TTY::ioctl(Process& process, unsigned request, unsigned arg) { + pid_t pgid; + Unix::termios* tp; + if (process.tty() != this) return -ENOTTY; switch (request) { case TIOCGPGRP: - return pgid(); - case TIOCSPGRP: { + return m_pgid; + case TIOCSPGRP: // FIXME: Validate pgid fully. - pid_t pgid = static_cast(arg); + pgid = static_cast(arg); if (pgid < 0) return -EINVAL; - set_pgid(arg); + m_pgid = pgid; + return 0; + case TCGETS: + tp = reinterpret_cast(arg); + if (!process.validate_write(tp, sizeof(Unix::termios))) + return -EFAULT; + *tp = m_termios; + return 0; + case TCSETS: + tp = reinterpret_cast(arg); + if (!process.validate_read(tp, sizeof(Unix::termios))) + return -EFAULT; + set_termios(*tp); return 0; } - } + ASSERT_NOT_REACHED(); return -EINVAL; } diff --git a/LibC/sys/ioctl_numbers.h b/LibC/sys/ioctl_numbers.h index c0c0fe23d7..ad4fdc0e9b 100644 --- a/LibC/sys/ioctl_numbers.h +++ b/LibC/sys/ioctl_numbers.h @@ -3,5 +3,9 @@ enum IOCtlNumber { TIOCGPGRP, TIOCSPGRP, + TCGETS, + TCSETS, + TCSETSW, + TCSETSF, }; diff --git a/LibC/termios.cpp b/LibC/termios.cpp index 03851f20c3..32ca610c67 100644 --- a/LibC/termios.cpp +++ b/LibC/termios.cpp @@ -1,20 +1,26 @@ #include #include #include +#include #include extern "C" { int tcgetattr(int fd, struct termios* t) { - int rc = Syscall::invoke(Syscall::SC_tcgetattr, (dword)fd, (dword)t); - __RETURN_WITH_ERRNO(rc, rc, -1); + return ioctl(fd, TCGETS, t); } int tcsetattr(int fd, int optional_actions, const struct termios* t) { - int rc = Syscall::invoke(Syscall::SC_tcsetattr, (dword)fd, (dword)optional_actions, (dword)t); - __RETURN_WITH_ERRNO(rc, rc, -1); + switch (optional_actions) { + case TCSANOW: + return ioctl(fd, TCSETS, t); + case TCSADRAIN: + return ioctl(fd, TCSETSW, t); + case TCSAFLUSH: + return ioctl(fd, TCSETSF, t); + } } int tcflow(int fd, int action)