Kernel/LibC: implement proper getpgid and setpgid

This commit is contained in:
Bananymous
2023-08-22 14:53:12 +03:00
parent d634fec8dc
commit 60a2185ee6
5 changed files with 117 additions and 12 deletions

View File

@@ -80,12 +80,13 @@ namespace Kernel
BAN::ErrorOr<long> sys_setegid(gid_t);
BAN::ErrorOr<long> sys_setreuid(uid_t, uid_t);
BAN::ErrorOr<long> sys_setregid(gid_t, gid_t);
BAN::ErrorOr<long> sys_setpgrp();
BAN::ErrorOr<long> sys_setpgid(pid_t, pid_t);
BAN::ErrorOr<long> sys_getuid() const { return m_credentials.ruid(); }
BAN::ErrorOr<long> sys_getgid() const { return m_credentials.rgid(); }
BAN::ErrorOr<long> sys_geteuid() const { return m_credentials.euid(); }
BAN::ErrorOr<long> sys_getegid() const { return m_credentials.egid(); }
BAN::ErrorOr<long> sys_getpgid(pid_t);
BAN::ErrorOr<long> sys_open(BAN::StringView, int, mode_t = 0);
BAN::ErrorOr<long> sys_openat(int, BAN::StringView, int, mode_t = 0);

View File

@@ -1152,11 +1152,104 @@ namespace Kernel
return 0;
}
BAN::ErrorOr<long> Process::sys_setpgrp()
BAN::ErrorOr<long> 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<long> 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<BAN::String> Process::absolute_path_of(BAN::StringView path) const

View File

@@ -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);