Kernel/LibC: implement proper getpgid and setpgid

This commit is contained in:
Bananymous 2023-08-22 14:53:12 +03:00
parent 25c021c15b
commit 97ea4986af
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);

View File

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

View File

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