diff --git a/Kernel/FileSystem/ProcFS.cpp b/Kernel/FileSystem/ProcFS.cpp index 37da0d35a9..12250da5c5 100644 --- a/Kernel/FileSystem/ProcFS.cpp +++ b/Kernel/FileSystem/ProcFS.cpp @@ -822,9 +822,9 @@ Optional procfs$all(InodeIdentifier) } process_object.add("pid", process.pid().value()); - process_object.add("pgid", process.tty() ? process.tty()->pgid() : 0); - process_object.add("pgp", process.pgid()); - process_object.add("sid", process.sid()); + process_object.add("pgid", process.tty() ? process.tty()->pgid().value() : 0); + process_object.add("pgp", process.pgid().value()); + process_object.add("sid", process.sid().value()); process_object.add("uid", process.uid()); process_object.add("gid", process.gid()); process_object.add("ppid", process.ppid().value()); diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index e281bfc364..4a6eefb07c 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -100,7 +100,8 @@ ProcessID Process::allocate_pid() // Overflow is UB, and negative PIDs wreck havoc. // TODO: Handle PID overflow // For example: Use an Atomic, mask the most significant bit, - // retry if PID is already taken as a PID, taken as a TID, or zero. + // retry if PID is already taken as a PID, taken as a TID, + // takes as a PGID, taken as a SID, or zero. return next_pid.fetch_add(1, AK::MemoryOrder::memory_order_acq_rel); } diff --git a/Kernel/Process.h b/Kernel/Process.h index d024e629ab..f06af2732b 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -153,11 +153,14 @@ public: const PageDirectory& page_directory() const { return *m_page_directory; } static RefPtr from_pid(ProcessID); + static SessionID get_sid_from_pgid(ProcessGroupID pgid); const String& name() const { return m_name; } ProcessID pid() const { return m_pid; } - pid_t sid() const { return m_sid; } - pid_t pgid() const { return m_pgid; } + SessionID sid() const { return m_sid; } + bool is_session_leader() const { return m_sid.value() == m_pid.value(); } + ProcessGroupID pgid() const { return m_pgid; } + bool is_group_leader() const { return m_pgid.value() == m_pid.value(); } const FixedArray& extra_gids() const { return m_extra_gids; } uid_t euid() const { return m_euid; } gid_t egid() const { return m_egid; } @@ -179,7 +182,7 @@ public: template static void for_each(Callback); template - static void for_each_in_pgrp(pid_t, Callback); + static void for_each_in_pgrp(ProcessGroupID, Callback); template void for_each_child(Callback); template @@ -617,8 +620,8 @@ private: String m_name; ProcessID m_pid { 0 }; - pid_t m_sid { 0 }; - pid_t m_pgid { 0 }; + SessionID m_sid { 0 }; + ProcessGroupID m_pgid { 0 }; uid_t m_euid { 0 }; gid_t m_egid { 0 }; @@ -772,7 +775,7 @@ inline void Process::for_each_thread(Callback callback) const } template -inline void Process::for_each_in_pgrp(pid_t pgid, Callback callback) +inline void Process::for_each_in_pgrp(ProcessGroupID pgid, Callback callback) { ASSERT_INTERRUPTS_DISABLED(); ScopedSpinLock lock(g_processes_lock); diff --git a/Kernel/Syscalls/kill.cpp b/Kernel/Syscalls/kill.cpp index 2ac7dd712f..6331280f3b 100644 --- a/Kernel/Syscalls/kill.cpp +++ b/Kernel/Syscalls/kill.cpp @@ -52,7 +52,8 @@ KResult Process::do_killpg(pid_t pgrp, int signal) // Send the signal to all processes in the given group. if (pgrp == 0) { // Send the signal to our own pgrp. - pgrp = pgid(); + // FIXME: PIF/PGID INCOMPLETE + pgrp = pgid().value(); } bool group_was_empty = true; diff --git a/Kernel/Syscalls/setpgid.cpp b/Kernel/Syscalls/setpgid.cpp index 5561131fbb..457f44e7ed 100644 --- a/Kernel/Syscalls/setpgid.cpp +++ b/Kernel/Syscalls/setpgid.cpp @@ -33,14 +33,14 @@ pid_t Process::sys$getsid(pid_t pid) { REQUIRE_PROMISE(proc); if (pid == 0) - return m_sid; + return m_sid.value(); ScopedSpinLock lock(g_processes_lock); auto process = Process::from_pid(pid); if (!process) return -ESRCH; if (m_sid != process->m_sid) return -EPERM; - return process->m_sid; + return process->m_sid.value(); } pid_t Process::sys$setsid() @@ -48,44 +48,49 @@ pid_t Process::sys$setsid() REQUIRE_PROMISE(proc); InterruptDisabler disabler; bool found_process_with_same_pgid_as_my_pid = false; - // FIXME: PID/PGID ISSUE? Process::for_each_in_pgrp(pid().value(), [&](auto&) { found_process_with_same_pgid_as_my_pid = true; return IterationDecision::Break; }); if (found_process_with_same_pgid_as_my_pid) return -EPERM; + // Create a new Session and a new ProcessGroup. m_sid = m_pid.value(); m_pgid = m_pid.value(); m_tty = nullptr; - return m_sid; + return m_sid.value(); } pid_t Process::sys$getpgid(pid_t pid) { REQUIRE_PROMISE(proc); if (pid == 0) - return m_pgid; + return m_pgid.value(); ScopedSpinLock lock(g_processes_lock); // FIXME: Use a ProcessHandle auto process = Process::from_pid(pid); if (!process) return -ESRCH; - return process->m_pgid; + return process->m_pgid.value(); } pid_t Process::sys$getpgrp() { REQUIRE_PROMISE(stdio); - return m_pgid; + return m_pgid.value(); } -static pid_t get_sid_from_pgid(pid_t pgid) +SessionID Process::get_sid_from_pgid(ProcessGroupID pgid) { + // FIXME: This xor sys$setsid() uses the wrong locking mechanism. ScopedSpinLock lock(g_processes_lock); - auto group_leader = Process::from_pid(pgid); - if (!group_leader) - return -1; - return group_leader->sid(); + + SessionID sid { -1 }; + Process::for_each_in_pgrp(pgid, [&](auto& process) { + sid = process.sid(); + return IterationDecision::Break; + }); + + return sid; } int Process::sys$setpgid(pid_t specified_pid, pid_t specified_pgid) @@ -105,7 +110,7 @@ int Process::sys$setpgid(pid_t specified_pid, pid_t specified_pgid) // of the calling process or of a child process of the calling process. return -ESRCH; } - if (process->pid() == process->sid()) { + if (process->is_session_leader()) { // The process indicated by the pid argument is a session leader. return -EPERM; } @@ -116,10 +121,9 @@ int Process::sys$setpgid(pid_t specified_pid, pid_t specified_pgid) return -EPERM; } - // FIXME: PID/PGID INCOMPLETE - pid_t new_pgid = specified_pgid ? specified_pgid : process->m_pid.value(); - pid_t current_sid = get_sid_from_pgid(process->m_pgid); - pid_t new_sid = get_sid_from_pgid(new_pgid); + ProcessGroupID new_pgid = specified_pgid ? ProcessGroupID(specified_pgid) : process->m_pid.value(); + SessionID current_sid = sid(); + SessionID new_sid = get_sid_from_pgid(new_pgid); if (current_sid != new_sid) { // Can't move a process between sessions. return -EPERM; diff --git a/Kernel/TTY/TTY.cpp b/Kernel/TTY/TTY.cpp index e3b655d24f..28e781927e 100644 --- a/Kernel/TTY/TTY.cpp +++ b/Kernel/TTY/TTY.cpp @@ -159,6 +159,7 @@ void TTY::emit(u8 ch) if (auto parent = Process::from_pid(m_process->ppid())) (void)parent->send_signal(SIGCHLD, m_process); } + // TODO: Else send it to the session leader maybe? return; } } @@ -253,7 +254,7 @@ void TTY::generate_signal(int signal) return; if (should_flush_on_signal()) flush_input(); - dbg() << tty_name() << ": Send signal " << signal << " to everyone in pgrp " << pgid(); + dbg() << tty_name() << ": Send signal " << signal << " to everyone in pgrp " << pgid().value(); InterruptDisabler disabler; // FIXME: Iterate over a set of process handles instead? Process::for_each_in_pgrp(pgid(), [&](auto& process) { dbg() << tty_name() << ": Send signal " << signal << " to " << process; @@ -291,7 +292,6 @@ int TTY::ioctl(FileDescription&, unsigned request, FlatPtr arg) { REQUIRE_PROMISE(tty); auto& current_process = *Process::current(); - pid_t pgid; termios* user_termios; winsize* user_winsize; @@ -304,23 +304,21 @@ int TTY::ioctl(FileDescription&, unsigned request, FlatPtr arg) #endif switch (request) { case TIOCGPGRP: - return this->pgid(); - case TIOCSPGRP: - pgid = static_cast(arg); + return this->pgid().value(); + case TIOCSPGRP: { + ProcessGroupID pgid = static_cast(arg); if (pgid <= 0) return -EINVAL; - { - InterruptDisabler disabler; - auto process = Process::from_pid(pgid); - if (!process) - return -EPERM; - if (pgid != process->pgid()) - return -EPERM; - if (current_process.sid() != process->sid()) - return -EPERM; - m_process = process->make_weak_ptr(); - } + InterruptDisabler disabler; + auto process = Process::from_pid(pgid.value()); + SessionID new_sid = process ? process->sid() : Process::get_sid_from_pgid(pgid); + if (!new_sid || new_sid != current_process.sid()) + return -EPERM; + if (process && pgid != process->pgid()) + return -EPERM; + m_process = process ? process->make_weak_ptr() : WeakPtr(); return 0; + } case TCGETS: { user_termios = reinterpret_cast(arg); if (!current_process.validate_write(user_termios, sizeof(termios))) @@ -395,7 +393,7 @@ void TTY::hang_up() generate_signal(SIGHUP); } -pid_t TTY::pgid() const +ProcessGroupID TTY::pgid() const { return m_process ? m_process->pgid() : 0; } diff --git a/Kernel/TTY/TTY.h b/Kernel/TTY/TTY.h index cbaf23e9e6..e8febbd079 100644 --- a/Kernel/TTY/TTY.h +++ b/Kernel/TTY/TTY.h @@ -50,7 +50,7 @@ public: unsigned short rows() const { return m_rows; } unsigned short columns() const { return m_columns; } - pid_t pgid() const; + ProcessGroupID pgid() const; void set_termios(const termios&); bool should_generate_signals() const { return m_termios.c_lflag & ISIG; }