From fa8a6e20abdb18a9839298923dcf0796d0f2bbd4 Mon Sep 17 00:00:00 2001 From: "K. Lange" Date: Fri, 19 Jan 2024 20:12:34 +0900 Subject: [PATCH] tty: support setting controlling session This is... kinda backwards? But it works sufficiently for us. Every TTY has at most one controlling session - every session is supposed have at most one controlling terminal, too, but we don't implement that part yet. --- kernel/vfs/tty.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/kernel/vfs/tty.c b/kernel/vfs/tty.c index 706d3aee..8812da86 100644 --- a/kernel/vfs/tty.c +++ b/kernel/vfs/tty.c @@ -320,6 +320,24 @@ int pty_ioctl(pty_t * pty, unsigned long request, void * argp) { validate(argp); *(pid_t *)argp = pty->fg_proc; return 0; + case TIOCSCTTY: + /* If this is already the control session, quietly ignore. */ + if (this_core->current_process->session == this_core->current_process->id && + pty->ct_proc == this_core->current_process->session) { + return 0; + } + /* If we aren't a session leader, we can't do this. */ + if (this_core->current_process->session != this_core->current_process->id) { + return -EPERM; + } + /* If there's already a control session, only root can steal control, and only if *argp is 1 + * (on Linux, that's "if argp is 1", but we kinda messed this up by checking ioctl argp stuff + * for bounds validity in the system call layer, so instead we use a pointer to 1... */ + if (pty->ct_proc && (!argp || (*(int*)argp != 1) || this_core->current_process->user != 0)) { + return -EPERM; + } + pty->ct_proc = this_core->current_process->session; + return 0; case TCSETS: case TCSETSW: if (!argp) return -EINVAL;