Browse Source

Reimplement tcsetattr/tcgetattr as ioctls.

Andreas Kling 6 years ago
parent
commit
084287ca45
7 changed files with 55 additions and 49 deletions
  1. 18 34
      Kernel/Process.cpp
  2. 3 0
      Kernel/Process.h
  3. 0 4
      Kernel/Syscall.cpp
  4. 0 2
      Kernel/Syscall.h
  5. 20 5
      Kernel/TTY.cpp
  6. 4 0
      LibC/sys/ioctl_numbers.h
  7. 10 4
      LibC/termios.cpp

+ 18 - 34
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<dword>(address) & PAGE_MASK) != ((reinterpret_cast<dword>(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<dword>(address) & PAGE_MASK) != ((reinterpret_cast<dword>(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);

+ 3 - 0
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; }
 

+ 0 - 4
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:

+ 0 - 2
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) \
 
 

+ 20 - 5
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<pid_t>(arg);
+        pgid = static_cast<pid_t>(arg);
         if (pgid < 0)
             return -EINVAL;
-        set_pgid(arg);
+        m_pgid = pgid;
+        return 0;
+    case TCGETS:
+        tp = reinterpret_cast<Unix::termios*>(arg);
+        if (!process.validate_write(tp, sizeof(Unix::termios)))
+            return -EFAULT;
+        *tp = m_termios;
+        return 0;
+    case TCSETS:
+        tp = reinterpret_cast<Unix::termios*>(arg);
+        if (!process.validate_read(tp, sizeof(Unix::termios)))
+            return -EFAULT;
+        set_termios(*tp);
         return 0;
     }
-    }
+    ASSERT_NOT_REACHED();
     return -EINVAL;
 }

+ 4 - 0
LibC/sys/ioctl_numbers.h

@@ -3,5 +3,9 @@
 enum IOCtlNumber {
     TIOCGPGRP,
     TIOCSPGRP,
+    TCGETS,
+    TCSETS,
+    TCSETSW,
+    TCSETSF,
 };
 

+ 10 - 4
LibC/termios.cpp

@@ -1,20 +1,26 @@
 #include <assert.h>
 #include <errno.h>
 #include <termios.h>
+#include <sys/ioctl.h>
 #include <Kernel/Syscall.h>
 
 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)