From d8f0dd6f3b36987c2a8021e16341dda16cbb7ab1 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 2 Nov 2018 12:56:51 +0100 Subject: [PATCH] Start working on sessions and process groups. --- Kernel/ProcFileSystem.cpp | 6 ++- Kernel/Process.cpp | 97 +++++++++++++++++++++++++++++++++++++++ Kernel/Process.h | 9 ++++ Kernel/Syscall.cpp | 10 ++++ Kernel/Syscall.h | 5 ++ LibC/unistd.cpp | 25 ++++++++++ LibC/unistd.h | 5 ++ Userland/sh.cpp | 2 + 8 files changed, 157 insertions(+), 2 deletions(-) diff --git a/Kernel/ProcFileSystem.cpp b/Kernel/ProcFileSystem.cpp index 45cb6da3d2..e899f4f314 100644 --- a/Kernel/ProcFileSystem.cpp +++ b/Kernel/ProcFileSystem.cpp @@ -277,10 +277,12 @@ ByteBuffer procfs$summary() auto processes = Process::allProcesses(); auto buffer = ByteBuffer::createUninitialized(processes.size() * 256); char* ptr = (char*)buffer.pointer(); - ptr += ksprintf(ptr, "PID OWNER STATE PPID NSCHED FDS TTY NAME\n"); + ptr += ksprintf(ptr, "PID PGP SID OWNER STATE PPID NSCHED FDS TTY NAME\n"); for (auto* process : processes) { - ptr += ksprintf(ptr, "% 5u % 4u % 8s % 5u % 10u % 3u % 4s %s\n", + ptr += ksprintf(ptr, "% 3u % 3u % 3u % 4u % 8s % 3u % 9u % 3u % 4s %s\n", process->pid(), + process->pgid(), + process->sid(), process->uid(), toString(process->state()), process->parentPID(), diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 0aad37c661..14deb2812a 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -129,6 +129,16 @@ void Process::allocateLDT() m_tss.ldt = m_ldt_selector; } +template +static void forEachProcess(Callback callback) +{ + ASSERT_INTERRUPTS_DISABLED(); + for (auto* process = s_processes->head(); process; process = process->next()) { + if (!callback(*process)) + break; + } +} + Vector Process::allProcesses() { InterruptDisabler disabler; @@ -406,6 +416,16 @@ Process::Process(String&& name, uid_t uid, gid_t gid, pid_t parentPID, RingLevel , m_tty(tty) , m_parentPID(parentPID) { + { + // FIXME: Use a ProcessHandle? Presumably we're executing *IN* the parent right now though.. + InterruptDisabler disabler; + if (auto* parent = Process::fromPID(m_parentPID)) { + m_sid = parent->m_sid; + m_pgid = parent->m_pgid; + } + + } + m_page_directory = (PageDirectory*)kmalloc_page_aligned(sizeof(PageDirectory)); MM.populate_page_directory(*this); @@ -1152,3 +1172,80 @@ bool Process::validate_user_write(LinearAddress laddr) const InterruptDisabler disabler; return MM.validate_user_write(*this, laddr); } + +pid_t Process::sys$getsid(pid_t pid) +{ + if (pid == 0) + return m_sid; + InterruptDisabler disabler; + auto* process = Process::fromPID(pid); + if (!process) + return -ESRCH; + if (m_sid != process->m_sid) + return -EPERM; + return process->m_sid; +} + +pid_t Process::sys$setsid() +{ + InterruptDisabler disabler; + bool found_process_with_same_pgid_as_my_pid = false; + forEachProcess([&] (auto& process) { + if (process.pgid() == pid()) { + found_process_with_same_pgid_as_my_pid = true; + return false; + } + return true; + }); + if (found_process_with_same_pgid_as_my_pid) + return -EPERM; + m_sid = m_pid; + m_pgid = m_pid; + return m_sid; +} + +pid_t Process::sys$getpgid(pid_t pid) +{ + if (pid == 0) + return m_pgid; + InterruptDisabler disabler; // FIXME: Use a ProcessHandle + auto* process = Process::fromPID(pid); + if (!process) + return -ESRCH; + return process->m_pgid; +} + +pid_t Process::sys$getpgrp() +{ + return m_pgid; +} + +static pid_t get_sid_from_pgid(pid_t pgid) +{ + InterruptDisabler disabler; + auto* group_leader = Process::fromPID(pgid); + if (!group_leader) + return -1; + return group_leader->sid(); +} + +int Process::sys$setpgid(pid_t specified_pid, pid_t specified_pgid) +{ + InterruptDisabler disabler; // FIXME: Use a ProcessHandle + pid_t pid = specified_pid ? specified_pid : m_pid; + if (specified_pgid < 0) + return -EINVAL; + auto* process = Process::fromPID(pid); + if (!process) + return -ESRCH; + pid_t new_pgid = specified_pgid ? specified_pgid : process->m_pid; + pid_t current_sid = get_sid_from_pgid(process->m_pgid); + pid_t new_sid = get_sid_from_pgid(new_pgid); + if (current_sid != new_sid) { + // Can't move a process between sessions. + return -EPERM; + } + // FIXME: There are more EPERM conditions to check for here.. + process->m_pgid = new_pgid; + return 0; +} diff --git a/Kernel/Process.h b/Kernel/Process.h index b1cb535a74..12302ecbb1 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -50,6 +50,8 @@ public: const String& name() const { return m_name; } pid_t pid() const { return m_pid; } + pid_t sid() const { return m_sid; } + pid_t pgid() const { return m_pgid; } DWORD ticks() const { return m_ticks; } WORD selector() const { return m_farPtr.selector; } TSS32& tss() { return m_tss; } @@ -79,6 +81,11 @@ public: void setSelector(WORD s) { m_farPtr.selector = s; } void set_state(State s) { m_state = s; } + pid_t sys$setsid(); + pid_t sys$getsid(pid_t); + int sys$setpgid(pid_t pid, pid_t pgid); + pid_t sys$getpgrp(); + pid_t sys$getpgid(pid_t); uid_t sys$getuid(); gid_t sys$getgid(); pid_t sys$getpid(); @@ -160,6 +167,8 @@ private: pid_t m_pid { 0 }; uid_t m_uid { 0 }; gid_t m_gid { 0 }; + pid_t m_sid { 0 }; + pid_t m_pgid { 0 }; DWORD m_ticks { 0 }; DWORD m_ticksLeft { 0 }; DWORD m_stackTop0 { 0 }; diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index 2e24c7ec29..e8163a4465 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -114,6 +114,16 @@ DWORD handle(DWORD function, DWORD arg1, DWORD arg2, DWORD arg3) return current->sys$readlink((const char*)arg1, (char*)arg2, (size_t)arg3); case Syscall::PosixTtynameR: return current->sys$ttyname_r((int)arg1, (char*)arg2, (size_t)arg3); + case Syscall::PosixSetsid: + return current->sys$setsid(); + case Syscall::PosixGetsid: + return current->sys$getsid((pid_t)arg1); + case Syscall::PosixSetpgid: + return current->sys$setpgid((pid_t)arg1, (pid_t)arg2); + case Syscall::PosixGetpgid: + return current->sys$getpgid((pid_t)arg1); + case Syscall::PosixGetpgrp: + return current->sys$getpgrp(); default: kprintf("<%u> int0x80: Unknown function %x requested {%x, %x, %x}\n", current->pid(), function, arg1, arg2, arg3); break; diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index 1e952d8598..f35658bf2a 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -40,6 +40,11 @@ enum Function { PosixTtynameR = 0x2008, PosixStat = 0x2009, GetEnvironment = 0x2010, + PosixGetsid = 0x2011, + PosixSetsid = 0x2012, + PosixGetpgid = 0x2013, + PosixSetpgid = 0x2014, + PosixGetpgrp = 0x2015, }; void initialize(); diff --git a/LibC/unistd.cpp b/LibC/unistd.cpp index 53f6b2aab2..7f6e266f37 100644 --- a/LibC/unistd.cpp +++ b/LibC/unistd.cpp @@ -20,6 +20,31 @@ pid_t getpid() return Syscall::invoke(Syscall::PosixGetpid); } +pid_t setsid() +{ + return Syscall::invoke(Syscall::PosixSetsid); +} + +pid_t sys$getsid(pid_t pid) +{ + return Syscall::invoke(Syscall::PosixSetsid, (dword)pid); +} + +int setpgid(pid_t pid, pid_t pgid) +{ + return Syscall::invoke(Syscall::PosixSetpgid, (dword)pid, (dword)pgid); +} + +pid_t getpgid(pid_t pid) +{ + return Syscall::invoke(Syscall::PosixGetpgid, (dword)pid); +} + +pid_t getpgrp() +{ + return Syscall::invoke(Syscall::PosixGetpgrp); +} + int open(const char* path, int options) { int rc = Syscall::invoke(Syscall::PosixOpen, (dword)path, (dword)options); diff --git a/LibC/unistd.h b/LibC/unistd.h index 9212214998..9c73b778ef 100644 --- a/LibC/unistd.h +++ b/LibC/unistd.h @@ -8,6 +8,11 @@ __BEGIN_DECLS extern char** environ; inline int getpagesize() { return 4096; } +pid_t getsid(pid_t); +pid_t setsid(); +int setpgid(pid_t pid, pid_t pgid); +pid_t getpgid(pid_t); +pid_t getpgrp(); uid_t getuid(); gid_t getgid(); pid_t getpid(); diff --git a/Userland/sh.cpp b/Userland/sh.cpp index 264a748cf7..7ad8361153 100644 --- a/Userland/sh.cpp +++ b/Userland/sh.cpp @@ -14,6 +14,7 @@ struct GlobalState { const char* ttyname_short { nullptr }; char ttyname[32]; char hostname[32]; + pid_t sid; }; static GlobalState* g; @@ -171,6 +172,7 @@ static void greeting() int main(int, char**) { g = new GlobalState; + g->sid = setsid(); int rc = gethostname(g->hostname, sizeof(g->hostname)); if (rc < 0) perror("gethostname");