diff --git a/kernel/src/sys/exec.cpp b/kernel/src/sys/exec.cpp index fe6a8623..6fa4034c 100644 --- a/kernel/src/sys/exec.cpp +++ b/kernel/src/sys/exec.cpp @@ -117,6 +117,8 @@ Result sys_execve(Registers* regs, SyscallArgs args) current->signal_handlers[i] = { .sa_handler = SIG_DFL, .sa_mask = 0, .sa_flags = 0 }; } + current->has_called_exec = true; + kinfoln("exec: thread %lu was replaced with %s", current->id, path.chars()); return 0; diff --git a/kernel/src/sys/id.cpp b/kernel/src/sys/id.cpp index 4a82bbd8..89645357 100644 --- a/kernel/src/sys/id.cpp +++ b/kernel/src/sys/id.cpp @@ -95,6 +95,39 @@ Result sys_setegid(Registers*, SyscallArgs args) return 0; } +Result sys_setpgid(Registers*, SyscallArgs args) +{ + pid_t pid = (pid_t)args[0]; + pid_t pgid = (pid_t)args[1]; + + auto* current = Scheduler::current(); + if (pid == 0) pid = (pid_t)current->id; + if (pgid == 0) pgid = (pid_t)current->id; + + if (pgid < 0) return err(EINVAL); + + auto* thread = TRY(Result::from_option(Scheduler::find_by_pid(pid), ESRCH)); + if (thread != current && thread->parent != current) return err(ESRCH); + + // FIXME: Weird session stuff, we don't have that currently. + + if (thread->has_called_exec) return err(EPERM); + + if (pgid != (pid_t)current->id) + { + bool pgid_exists = false; + Scheduler::for_each_in_process_group(pgid, [&pgid_exists](Thread*) { + pgid_exists = true; + return false; + }); + if (!pgid_exists) return err(EPERM); + } + + thread->pgid = (u64)pgid; + + return 0; +} + Result sys_fchmodat(Registers*, SyscallArgs args) { int dirfd = (int)args[0]; diff --git a/kernel/src/thread/Scheduler.h b/kernel/src/thread/Scheduler.h index 4816b459..8ff2f939 100644 --- a/kernel/src/thread/Scheduler.h +++ b/kernel/src/thread/Scheduler.h @@ -45,6 +45,19 @@ namespace Scheduler } } + template void for_each_in_process_group(pid_t group, Callback callback) + { + for (Thread* current = g_threads.first().value_or(nullptr); current; + current = g_threads.next(current).value_or(nullptr)) + { + if (current->pgid == (u64)group) + { + bool should_continue = callback(current); + if (!should_continue) return; + } + } + } + void dump_state(); bool has_children(Thread* thread); diff --git a/kernel/src/thread/Thread.h b/kernel/src/thread/Thread.h index be90fab1..de69bbc6 100644 --- a/kernel/src/thread/Thread.h +++ b/kernel/src/thread/Thread.h @@ -57,6 +57,7 @@ struct Thread : public LinkedListNode Registers regs; u64 id; + u64 pgid { 0 }; Credentials auth; @@ -82,14 +83,14 @@ struct Thread : public LinkedListNode struct sigaction signal_handlers[NSIG]; sigset_t signal_mask { 0 }; - - int pending_signals { 0 }; + sigset_t pending_signals { 0 }; FPData fp_data; ThreadState state = ThreadState::Runnable; bool is_kernel { true }; + bool has_called_exec { false }; int status { 0 }; diff --git a/libc/include/math.h b/libc/include/math.h new file mode 100644 index 00000000..e69de29b diff --git a/libc/include/wchar.h b/libc/include/wchar.h new file mode 100644 index 00000000..e69de29b diff --git a/libc/src/unistd.cpp b/libc/src/unistd.cpp index cbf5a826..9b6e7b60 100644 --- a/libc/src/unistd.cpp +++ b/libc/src/unistd.cpp @@ -144,6 +144,12 @@ extern "C" __errno_return(rc, int); } + int setpgid(pid_t pid, pid_t pgid) + { + long rc = syscall(SYS_setpgid, pid, pgid); + __errno_return(rc, int); + } + int chown(const char* path, uid_t uid, gid_t gid) { long rc = syscall(SYS_fchownat, AT_FDCWD, path, uid, gid, 0); diff --git a/libluna/include/luna/Syscall.h b/libluna/include/luna/Syscall.h index c89beb66..ae216722 100644 --- a/libluna/include/luna/Syscall.h +++ b/libluna/include/luna/Syscall.h @@ -6,7 +6,7 @@ _e(getgid) _e(getegid) _e(setuid) _e(setgid) _e(seteuid) _e(setegid) _e(fchmodat) _e(fchownat) _e(ioctl) \ _e(fstatat) _e(chdir) _e(getcwd) _e(unlinkat) _e(uname) _e(sethostname) _e(dup2) _e(pipe) _e(mount) \ _e(umount) _e(pstat) _e(getrusage) _e(symlinkat) _e(readlinkat) _e(umask) _e(linkat) _e(faccessat) \ - _e(pivot_root) _e(sigreturn) _e(sigaction) _e(kill) _e(sigprocmask) + _e(pivot_root) _e(sigreturn) _e(sigaction) _e(kill) _e(sigprocmask) _e(setpgid) enum Syscalls {