diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index f1fb007a..cf461472 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -80,12 +80,13 @@ namespace Kernel BAN::ErrorOr sys_setegid(gid_t); BAN::ErrorOr sys_setreuid(uid_t, uid_t); BAN::ErrorOr sys_setregid(gid_t, gid_t); - BAN::ErrorOr sys_setpgrp(); + BAN::ErrorOr sys_setpgid(pid_t, pid_t); BAN::ErrorOr sys_getuid() const { return m_credentials.ruid(); } BAN::ErrorOr sys_getgid() const { return m_credentials.rgid(); } BAN::ErrorOr sys_geteuid() const { return m_credentials.euid(); } BAN::ErrorOr sys_getegid() const { return m_credentials.egid(); } + BAN::ErrorOr sys_getpgid(pid_t); BAN::ErrorOr sys_open(BAN::StringView, int, mode_t = 0); BAN::ErrorOr sys_openat(int, BAN::StringView, int, mode_t = 0); diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index c0ab10e8..d894025f 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -1152,11 +1152,104 @@ namespace Kernel return 0; } - BAN::ErrorOr Process::sys_setpgrp() + BAN::ErrorOr Process::sys_setpgid(pid_t pid, pid_t pgid) + { + if (pgid < 0) + return BAN::Error::from_errno(EINVAL); + + LockGuard _(m_lock); + + if (pid == 0) + pid = m_pid; + if (pgid == 0) + pgid = m_pid; + + if (pid != pgid) + { + bool pgid_valid = false; + for_each_process_in_session(m_sid, + [&](Process& process) + { + if (process.pgrp() == pgid) + { + pgid_valid = true; + return BAN::Iteration::Break; + } + return BAN::Iteration::Continue; + } + ); + if (!pgid_valid) + return BAN::Error::from_errno(EPERM); + } + + if (m_pid == pid) + { + if (is_session_leader()) + return BAN::Error::from_errno(EPERM); + m_pgrp = pgid; + return 0; + } + + int error = ESRCH; + for_each_process( + [&](Process& process) + { + if (process.pid() != pid) + return BAN::Iteration::Continue; + + if (process.m_parent != m_pid) + error = ESRCH; + else if (process.is_session_leader()) + error = EPERM; + else if (process.m_has_called_exec) + error = EACCES; + else if (process.m_sid != m_sid) + error = EPERM; + else + { + error = 0; + process.m_pgrp = pgid; + } + + return BAN::Iteration::Break; + } + ); + + if (error == 0) + return 0; + return BAN::Error::from_errno(error); + } + + BAN::ErrorOr Process::sys_getpgid(pid_t pid) { LockGuard _(m_lock); - m_pgrp = pid(); - return pgrp(); + + if (pid == 0 || pid == m_pid) + return m_pgrp; + + pid_t result; + int error = ESRCH; + for_each_process( + [&](Process& process) + { + if (process.pid() != pid) + return BAN::Iteration::Continue; + + if (process.sid() != m_sid) + error = EPERM; + else + { + error = 0; + result = process.pgrp(); + } + + return BAN::Iteration::Break; + } + ); + + if (error == 0) + return result; + return BAN::Error::from_errno(error); } BAN::ErrorOr Process::absolute_path_of(BAN::StringView path) const diff --git a/kernel/kernel/Syscall.cpp b/kernel/kernel/Syscall.cpp index eac7cdb1..0847fccb 100644 --- a/kernel/kernel/Syscall.cpp +++ b/kernel/kernel/Syscall.cpp @@ -173,11 +173,11 @@ namespace Kernel case SYS_GET_PID: ret = Process::current().pid(); break; - case SYS_GET_PGRP: - ret = Process::current().pgrp(); + case SYS_GET_PGID: + ret = Process::current().sys_getpgid((pid_t)arg1); break; - case SYS_SET_PGRP: - ret = Process::current().sys_setpgrp(); + case SYS_SET_PGID: + ret = Process::current().sys_setpgid((pid_t)arg1, (pid_t)arg2); break; default: dwarnln("Unknown syscall {}", syscall); diff --git a/libc/include/sys/syscall.h b/libc/include/sys/syscall.h index 6e1548b5..25ba52dc 100644 --- a/libc/include/sys/syscall.h +++ b/libc/include/sys/syscall.h @@ -48,8 +48,8 @@ __BEGIN_DECLS #define SYS_SIGNAL_DONE 41 #define SYS_TCSETPGRP 42 #define SYS_GET_PID 43 -#define SYS_GET_PGRP 44 -#define SYS_SET_PGRP 45 +#define SYS_GET_PGID 44 +#define SYS_SET_PGID 45 __END_DECLS diff --git a/libc/unistd.cpp b/libc/unistd.cpp index 93be4e19..3f7f9199 100644 --- a/libc/unistd.cpp +++ b/libc/unistd.cpp @@ -210,7 +210,12 @@ gid_t getegid(void) pid_t getpgrp(void) { - return syscall(SYS_GET_PGRP); + return getpgid(0); +} + +pid_t getpgid(pid_t pid) +{ + return syscall(SYS_GET_PGID, pid); } int seteuid(uid_t uid) @@ -245,7 +250,13 @@ int setregid(gid_t rgid, gid_t egid) pid_t setpgrp(void) { - return syscall(SYS_SET_PGRP); + setpgid(0, 0); + return getpgrp(); +} + +int setpgid(pid_t pid, pid_t pgid) +{ + return syscall(SYS_SET_PGID, pid, pgid); } int tcsetpgrp(int fildes, pid_t pgid_id)