mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 20:22:45 +00:00 
			
		
		
		
	Kernel: Implement the killpg() syscall
This commit is contained in:
		
							parent
							
								
									1e1ddce9d8
								
							
						
					
					
						commit
						d29a078ab3
					
				
					 2 changed files with 59 additions and 18 deletions
				
			
		|  | @ -1455,8 +1455,12 @@ int Process::sys$killpg(int pgrp, int signum) | ||||||
| { | { | ||||||
|     if (signum < 1 || signum >= 32) |     if (signum < 1 || signum >= 32) | ||||||
|         return -EINVAL; |         return -EINVAL; | ||||||
|     (void)pgrp; |     if (pgrp < 0) | ||||||
|     ASSERT_NOT_REACHED(); |         return -EINVAL; | ||||||
|  | 
 | ||||||
|  |     InterruptDisabler disabler; | ||||||
|  | 
 | ||||||
|  |     return do_killpg(pgrp, signum); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int Process::sys$setuid(uid_t uid) | int Process::sys$setuid(uid_t uid) | ||||||
|  | @ -1514,16 +1518,59 @@ int Process::sys$isatty(int fd) | ||||||
|     return 1; |     return 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | KResult Process::do_kill(Process& process, int signal) | ||||||
|  | { | ||||||
|  |     // FIXME: Allow sending SIGCONT to everyone in the process group.
 | ||||||
|  |     // FIXME: Should setuid processes have some special treatment here?
 | ||||||
|  |     if (!is_superuser() && m_euid != process.m_uid && m_uid != process.m_uid) | ||||||
|  |         return KResult(-EPERM); | ||||||
|  |     if (process.is_ring0() && signal == SIGKILL) { | ||||||
|  |         kprintf("%s(%u) attempted to send SIGKILL to ring 0 process %s(%u)\n", name().characters(), m_pid, process.name().characters(), process.pid()); | ||||||
|  |         return KResult(-EPERM); | ||||||
|  |     } | ||||||
|  |     process.send_signal(signal, this); | ||||||
|  |     return KSuccess; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | KResult Process::do_killpg(pid_t pgrp, int signal) | ||||||
|  | { | ||||||
|  |     ASSERT(pgrp >= 0); | ||||||
|  | 
 | ||||||
|  |     // Send the signal to all processes in the given group.
 | ||||||
|  |     if (pgrp == 0) { | ||||||
|  |         // Send the signal to our own pgrp.
 | ||||||
|  |         pgrp = pgid(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     bool group_was_empty = true; | ||||||
|  |     bool any_succeeded = false; | ||||||
|  |     KResult error = KSuccess; | ||||||
|  | 
 | ||||||
|  |     Process::for_each_in_pgrp(pgrp, [&](auto& process) { | ||||||
|  |         group_was_empty = false; | ||||||
|  | 
 | ||||||
|  |         KResult res = do_kill(process, signal); | ||||||
|  |         if (res.is_success()) | ||||||
|  |             any_succeeded = true; | ||||||
|  |         else | ||||||
|  |             error = res; | ||||||
|  | 
 | ||||||
|  |         return IterationDecision::Continue; | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     if (group_was_empty) | ||||||
|  |         return KResult(-ESRCH); | ||||||
|  |     if (any_succeeded) | ||||||
|  |         return KSuccess; | ||||||
|  |     return error; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| int Process::sys$kill(pid_t pid, int signal) | int Process::sys$kill(pid_t pid, int signal) | ||||||
| { | { | ||||||
|     if (signal < 0 || signal >= 32) |     if (signal < 0 || signal >= 32) | ||||||
|         return -EINVAL; |         return -EINVAL; | ||||||
|     if (pid == 0) { |     if (pid <= 0) { | ||||||
|         Process::for_each_in_pgrp(pgid(), [&](auto& process) { |         return do_killpg(-pid, signal); | ||||||
|             process.send_signal(signal, this); |  | ||||||
|             return IterationDecision::Continue; |  | ||||||
|         }); |  | ||||||
|         return 0; |  | ||||||
|     } |     } | ||||||
|     if (pid == -1) { |     if (pid == -1) { | ||||||
|         // FIXME: Send to all processes.
 |         // FIXME: Send to all processes.
 | ||||||
|  | @ -1539,16 +1586,7 @@ int Process::sys$kill(pid_t pid, int signal) | ||||||
|     auto* peer = Process::from_pid(pid); |     auto* peer = Process::from_pid(pid); | ||||||
|     if (!peer) |     if (!peer) | ||||||
|         return -ESRCH; |         return -ESRCH; | ||||||
|     // FIXME: Allow sending SIGCONT to everyone in the process group.
 |     return do_kill(*peer, signal); | ||||||
|     // FIXME: Should setuid processes have some special treatment here?
 |  | ||||||
|     if (!is_superuser() && m_euid != peer->m_uid && m_uid != peer->m_uid) |  | ||||||
|         return -EPERM; |  | ||||||
|     if (peer->is_ring0() && signal == SIGKILL) { |  | ||||||
|         kprintf("%s(%u) attempted to send SIGKILL to ring 0 process %s(%u)\n", name().characters(), m_pid, peer->name().characters(), peer->pid()); |  | ||||||
|         return -EPERM; |  | ||||||
|     } |  | ||||||
|     peer->send_signal(signal, this); |  | ||||||
|     return 0; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int Process::sys$usleep(useconds_t usec) | int Process::sys$usleep(useconds_t usec) | ||||||
|  |  | ||||||
|  | @ -315,6 +315,9 @@ private: | ||||||
| 
 | 
 | ||||||
|     KResultOr<Vector<String>> find_shebang_interpreter_for_executable(const String& executable_path); |     KResultOr<Vector<String>> find_shebang_interpreter_for_executable(const String& executable_path); | ||||||
| 
 | 
 | ||||||
|  |     KResult do_kill(Process&, int signal); | ||||||
|  |     KResult do_killpg(pid_t pgrp, int signal); | ||||||
|  | 
 | ||||||
|     Thread* m_main_thread { nullptr }; |     Thread* m_main_thread { nullptr }; | ||||||
| 
 | 
 | ||||||
|     RefPtr<PageDirectory> m_page_directory; |     RefPtr<PageDirectory> m_page_directory; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Sergey Bugaev
						Sergey Bugaev