Reimplement tcsetattr/tcgetattr as ioctls.

This commit is contained in:
Andreas Kling 2018-11-16 15:41:48 +01:00
parent c99f8af66d
commit 084287ca45
Notes: sideshowbarker 2024-07-19 16:10:22 +09:00
7 changed files with 55 additions and 49 deletions

View file

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

View file

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

View file

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

View file

@ -62,8 +62,6 @@
__ENUMERATE_SYSCALL(fstat) \
__ENUMERATE_SYSCALL(access) \
__ENUMERATE_SYSCALL(fcntl) \
__ENUMERATE_SYSCALL(tcsetattr) \
__ENUMERATE_SYSCALL(tcgetattr) \
__ENUMERATE_SYSCALL(ioctl) \

View file

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

View file

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

View file

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