Serenity Operating System
at master 164 lines 5.3 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <Kernel/InterruptDisabler.h> 8#include <Kernel/Process.h> 9#include <Kernel/TTY/TTY.h> 10 11namespace Kernel { 12 13ErrorOr<FlatPtr> Process::sys$getsid(pid_t pid) 14{ 15 VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this); 16 TRY(require_promise(Pledge::stdio)); 17 if (pid == 0) 18 return sid().value(); 19 auto process = Process::from_pid_in_same_jail(pid); 20 if (!process) 21 return ESRCH; 22 if (sid() != process->sid()) 23 return EPERM; 24 return process->sid().value(); 25} 26 27ErrorOr<FlatPtr> Process::sys$setsid() 28{ 29 VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this); 30 TRY(require_promise(Pledge::proc)); 31 InterruptDisabler disabler; 32 bool found_process_with_same_pgid_as_my_pid = false; 33 TRY(Process::for_each_in_pgrp_in_same_jail(pid().value(), [&](auto&) -> ErrorOr<void> { 34 found_process_with_same_pgid_as_my_pid = true; 35 return {}; 36 })); 37 if (found_process_with_same_pgid_as_my_pid) 38 return EPERM; 39 // Create a new Session and a new ProcessGroup. 40 41 m_pg = TRY(ProcessGroup::try_create(ProcessGroupID(pid().value()))); 42 m_tty = nullptr; 43 return with_mutable_protected_data([&](auto& protected_data) -> ErrorOr<FlatPtr> { 44 protected_data.sid = pid().value(); 45 return protected_data.sid.value(); 46 }); 47} 48 49ErrorOr<FlatPtr> Process::sys$getpgid(pid_t pid) 50{ 51 VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this); 52 TRY(require_promise(Pledge::stdio)); 53 if (pid == 0) 54 return pgid().value(); 55 auto process = Process::from_pid_in_same_jail(pid); 56 if (!process) 57 return ESRCH; 58 return process->pgid().value(); 59} 60 61ErrorOr<FlatPtr> Process::sys$getpgrp() 62{ 63 VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this); 64 TRY(require_promise(Pledge::stdio)); 65 return pgid().value(); 66} 67 68SessionID Process::get_sid_from_pgid(ProcessGroupID pgid) 69{ 70 // FIXME: This xor sys$setsid() uses the wrong locking mechanism. 71 72 SessionID sid { -1 }; 73 MUST(Process::current().for_each_in_pgrp_in_same_jail(pgid, [&](auto& process) -> ErrorOr<void> { 74 sid = process.sid(); 75 return {}; 76 })); 77 78 return sid; 79} 80 81ErrorOr<FlatPtr> Process::sys$setpgid(pid_t specified_pid, pid_t specified_pgid) 82{ 83 VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this); 84 TRY(require_promise(Pledge::proc)); 85 ProcessID pid = specified_pid ? ProcessID(specified_pid) : this->pid(); 86 if (specified_pgid < 0) { 87 // The value of the pgid argument is less than 0, or is not a value supported by the implementation. 88 return EINVAL; 89 } 90 auto process = Process::from_pid_in_same_jail(pid); 91 if (!process) 92 return ESRCH; 93 if (process != this && process->ppid() != this->pid()) { 94 // The value of the pid argument does not match the process ID 95 // of the calling process or of a child process of the calling process. 96 return ESRCH; 97 } 98 if (process->is_session_leader()) { 99 // The process indicated by the pid argument is a session leader. 100 return EPERM; 101 } 102 if (process->ppid() == this->pid() && process->sid() != sid()) { 103 // The value of the pid argument matches the process ID of a child 104 // process of the calling process and the child process is not in 105 // the same session as the calling process. 106 return EPERM; 107 } 108 109 ProcessGroupID new_pgid = specified_pgid ? ProcessGroupID(specified_pgid) : process->pid().value(); 110 SessionID current_sid = sid(); 111 SessionID new_sid = get_sid_from_pgid(new_pgid); 112 if (new_sid != -1 && current_sid != new_sid) { 113 // Can't move a process between sessions. 114 return EPERM; 115 } 116 if (new_sid == -1 && new_pgid != process->pid().value()) { 117 // The value of the pgid argument is valid, but is not 118 // the calling pid, and is not an existing process group. 119 return EPERM; 120 } 121 // FIXME: There are more EPERM conditions to check for here.. 122 process->m_pg = TRY(ProcessGroup::try_find_or_create(new_pgid)); 123 return with_mutable_protected_data([&](auto& protected_data) -> ErrorOr<FlatPtr> { 124 auto credentials = this->credentials(); 125 126 auto new_credentials = TRY(Credentials::create( 127 credentials->uid(), 128 credentials->gid(), 129 credentials->euid(), 130 credentials->egid(), 131 credentials->suid(), 132 credentials->sgid(), 133 credentials->extra_gids(), 134 new_sid, 135 new_pgid)); 136 137 protected_data.credentials = move(new_credentials); 138 return 0; 139 }); 140} 141 142ErrorOr<FlatPtr> Process::sys$get_root_session_id(pid_t force_sid) 143{ 144 TRY(require_promise(Pledge::stdio)); 145 pid_t sid = (force_sid == -1) ? this->sid().value() : force_sid; 146 if (sid == 0) 147 return 0; 148 while (true) { 149 auto sid_process = Process::from_pid_in_same_jail(sid); 150 if (!sid_process) 151 return ESRCH; 152 auto parent_pid = sid_process->ppid().value(); 153 auto parent_process = Process::from_pid_in_same_jail(parent_pid); 154 if (!parent_process) 155 return ESRCH; 156 pid_t parent_sid = parent_process->sid().value(); 157 if (parent_sid == 0) 158 break; 159 sid = parent_sid; 160 } 161 return sid; 162} 163 164}