Browse Source

Start working on sessions and process groups.

Andreas Kling 6 years ago
parent
commit
d8f0dd6f3b
8 changed files with 157 additions and 2 deletions
  1. 4 2
      Kernel/ProcFileSystem.cpp
  2. 97 0
      Kernel/Process.cpp
  3. 9 0
      Kernel/Process.h
  4. 10 0
      Kernel/Syscall.cpp
  5. 5 0
      Kernel/Syscall.h
  6. 25 0
      LibC/unistd.cpp
  7. 5 0
      LibC/unistd.h
  8. 2 0
      Userland/sh.cpp

+ 4 - 2
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(),

+ 97 - 0
Kernel/Process.cpp

@@ -129,6 +129,16 @@ void Process::allocateLDT()
     m_tss.ldt = m_ldt_selector;
 }
 
+template<typename Callback>
+static void forEachProcess(Callback callback)
+{
+    ASSERT_INTERRUPTS_DISABLED();
+    for (auto* process = s_processes->head(); process; process = process->next()) {
+        if (!callback(*process))
+            break;
+    }
+}
+
 Vector<Process*> 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;
+}

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

+ 10 - 0
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;

+ 5 - 0
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();

+ 25 - 0
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);

+ 5 - 0
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();

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