diff --git a/kernel/include/sched.h b/kernel/include/sched.h index db0035c69be6dc9938a08a6aab84c6149ff28902..9f5647a751802505c96e7fe4563ad739ad825489 100644 --- a/kernel/include/sched.h +++ b/kernel/include/sched.h @@ -33,8 +33,11 @@ struct pcb_t uintptr_t user_sp; uintptr_t kernel_sp_base; uintptr_t *pgdir; - pid_t pid; - pid_t ppid; + pid_t pid; // process id + pid_t ppid; // parent process id + pid_t tid; // thread id + pid_t pgid; // process group id + pid_t sid; // session id proc_status_t status; int exit_status; @@ -66,6 +69,8 @@ struct pcb_t // real, effective, and saved user/group IDs uid_t ruid, euid, suid; gid_t rgid, egid, sgid; + // supplementary group IDs + std::list<gid_t> supgids; char name[16]; // for debug }; @@ -109,10 +114,17 @@ uid_t getuid(); uid_t geteuid(); gid_t getgid(); gid_t getegid(); +pid_t gettid(); pcb_t *get_current_proc(); clock_t do_times(tms *buf); int do_kill(pid_t pid, int signum); int do_tkill(pid_t pid, int signum); int do_tgkill(pid_t tgid, pid_t pid, int signum); +int setpgid(pid_t pid, pid_t pgid); +pid_t getpgid(pid_t pid); +pid_t getsid(pid_t pid); +pid_t setsid(); +int getgroups(int size, gid_t *list); +int setgroups(size_t size, const gid_t *list); #endif \ No newline at end of file diff --git a/kernel/scheduler/sched.cpp b/kernel/scheduler/sched.cpp index fa7701c54db3aecfe27d9442108d0eff9b53189a..2659b6bd0a7b4da3672232dc364a879bd809f9ef 100644 --- a/kernel/scheduler/sched.cpp +++ b/kernel/scheduler/sched.cpp @@ -153,6 +153,9 @@ void init_pcb(hartid_t hartid) { proc->user_sp = alloc_page(1, proc->memory_list) + PAGE_SIZE; proc->pgdir = kernel_pgdir; proc->ppid = 0; + proc->tid = 0; + proc->pgid = 0; + proc->sid = 0; proc->status = RUNNING; // fs @@ -171,6 +174,8 @@ void init_pcb(hartid_t hartid) { proc->rgid = 0; proc->egid = 0; proc->sgid = 0; + // supplementary group list = root + proc->supgids.push_back(0); } void init_pcb_cwd() { @@ -188,6 +193,9 @@ pid_t fork(Context *c, void *stack) pcb_t *pproc = get_current_proc(); pcb_t *proc = alloc_pcb(); proc->ppid = pproc->pid; + proc->tid = proc->pid; // use pid as tid + proc->pgid = proc->pid; // use pid as pgid + proc->sid = pproc->sid; // same session with parent strncpy(proc->name, pproc->name, 16); proc->pgdir = fork_pgdir(pproc->pgdir, proc->memory_list); @@ -229,6 +237,10 @@ pid_t fork(Context *c, void *stack) proc->rgid = pproc->rgid; proc->egid = pproc->egid; proc->sgid = pproc->sgid; + // supplementary groups = parent's + for (auto gid : pproc->supgids) { + proc->supgids.push_back(gid); + } proc->status = READY; ready_queue.push_back(proc); @@ -301,7 +313,11 @@ pid_t kernel_execve(const char *pathname, char *const argv[], char *const envp[] pcb_t *pproc = get_current_proc(); pcb_t *proc = alloc_pcb(); strncpy(proc->name, pathname, 16); - proc->ppid = 0; + // proc->pid should be 1, pproc->pid should be 0 + proc->ppid = pproc->pid; + proc->tid = proc->pid; + proc->pgid = proc->pid; + proc->sid = proc->pid; proc->pgdir = reinterpret_cast<uintptr_t*>(alloc_page(1, proc->memory_list)); memcpy(proc->pgdir, kernel_pgdir, PAGE_SIZE); @@ -359,6 +375,18 @@ pid_t kernel_execve(const char *pathname, char *const argv[], char *const envp[] proc->sched_time = 0; proc->times = {0}; + // real, effective, saved uid/gid = parent's + proc->ruid = pproc->ruid; + proc->euid = pproc->euid; + proc->suid = pproc->suid; + proc->rgid = pproc->rgid; + proc->egid = pproc->egid; + proc->sgid = pproc->sgid; + // supplementary groups = parent's + for (auto gid : pproc->supgids) { + proc->supgids.push_back(gid); + } + proc->status = READY; ready_queue.push_back(proc); @@ -509,6 +537,10 @@ gid_t getegid() { return get_current_proc()->egid; } +pid_t gettid() { + return get_current_proc()->tid; +} + pcb_t *get_current_proc() { return hart[get_hartid()].proc; } @@ -554,3 +586,52 @@ int do_tgkill(pid_t tgid, pid_t pid, int signum) { return do_kill(pid, signum); // FIXME } + +int setpgid(pid_t pid, pid_t pgid) { + // FIXME: source and destination process groups must in the same session + pcb_t *proc = pid == 0 ? get_current_proc() : find_pcb(pid); + if (proc == nullptr) return -1; + proc->pgid = pgid == 0 ? proc->pid : pgid; + return 0; +} + +pid_t getpgid(pid_t pid) { + pcb_t *proc = pid == 0 ? get_current_proc() : find_pcb(pid); + if (proc == nullptr) return -1; + return proc->pgid; +} + +pid_t getsid(pid_t pid) { + pcb_t *proc = pid == 0 ? get_current_proc() : find_pcb(pid); + if (proc == nullptr) return -1; + return proc->sid; +} + +pid_t setsid() { + pcb_t *proc = get_current_proc(); + if (proc->pgid == proc->pid) return -1; // already process group leader + proc->sid = proc->pid; + proc->pgid = proc->pid; + return proc->sid; +} + +int getgroups(int size, gid_t *list) { + pcb_t *proc = get_current_proc(); + int n = proc->supgids.size(); + if (size == 0) return n; + if (size < n) return -1; + for (auto gid: proc->supgids) { + *list++ = gid; + } + return n; +} + +int setgroups(size_t size, const gid_t *list) { + if (size != 0 && list == nullptr) return -1; + pcb_t *proc = get_current_proc(); + proc->supgids.clear(); + for (size_t i = 0; i < size; i++) { + proc->supgids.push_back(list[i]); + } + return 0; +} diff --git a/kernel/syscall/syscall.cpp b/kernel/syscall/syscall.cpp index 42d1c105aca50dd079636da4522f6658f495b238..c4a149ddad61fc5dc0ff0fec4e6740e00cd660c9 100644 --- a/kernel/syscall/syscall.cpp +++ b/kernel/syscall/syscall.cpp @@ -766,33 +766,27 @@ static void sys_times(Context *c) { } static void sys_setpgid(Context *c) { - fmt::err("unimplemented syscall setpgid\n"); - sys_unimplemented(c); + a0 = setpgid(a0, a1); } static void sys_getpgid(Context *c) { - fmt::err("unimplemented syscall getpgid\n"); - sys_unimplemented(c); + a0 = getpgid(a0); } static void sys_getsid(Context *c) { - fmt::err("unimplemented syscall getsid\n"); - sys_unimplemented(c); + a0 = getsid(a0); } static void sys_setsid(Context *c) { - fmt::err("unimplemented syscall setsid\n"); - sys_unimplemented(c); + a0 = setsid(); } static void sys_getgroups(Context *c) { - fmt::err("unimplemented syscall getgroups\n"); - sys_unimplemented(c); + a0 = getgroups(a0, (gid_t *) a1); } static void sys_setgroups(Context *c) { - fmt::err("unimplemented syscall setgroups\n"); - sys_unimplemented(c); + a0 = setgroups(a0, (const gid_t *) a1); } static void sys_uname(Context *c) { @@ -878,8 +872,7 @@ static void sys_getegid(Context *c) { } static void sys_gettid(Context *c) { - fmt::err("unimplemented syscall gettid\n"); - sys_unimplemented(c); + a0 = gettid(); } static void sys_sysinfo(Context *c) { diff --git a/libs/include/list.h b/libs/include/list.h index 67e8c15a916283cc0a8cc6d0a3e203a62b388ee2..55a901a3c0af5105ee38b70075797a81486f6dc9 100644 --- a/libs/include/list.h +++ b/libs/include/list.h @@ -2,6 +2,7 @@ #define __LIST_H__ #include <mem.h> +#include <stddef.h> namespace std { @@ -37,16 +38,19 @@ class list private: ListNode_t<T> head_guard; ListNode_t<T> *head, *tail; + size_t __size; public: typedef T value_type; typedef T* pointer; typedef T& reference; typedef ListIterator<T> iterator; + typedef size_t size_type; list() { head_guard.prev = head_guard.next = nullptr; head = tail = &head_guard; + __size = 0; } iterator begin() { return iterator(head); } @@ -70,6 +74,7 @@ public: tail->prev = p; p->next = tail; } + ++ __size; } void pop_front() @@ -81,6 +86,7 @@ public: head->prev = nullptr; if (_head != &head_guard) destroy<ListNode_t<T>>(_head); + -- __size; } iterator erase(iterator __position) @@ -102,12 +108,15 @@ public: iterator ret(p->next); if (p != &head_guard) destroy<ListNode_t<T>>(p); + -- __size; return ret; } } reference front() { return head->value; } bool empty() const { return head == tail; } + size_type size() const { return __size; } + void clear() { while (!empty()) pop_front(); } }; }