From 6a8e60913ac470c704510a733d40d3fab3ecb00d Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 7 Dec 2006 00:16:07 +0000 Subject: * Move killUser() to libutil so that the setuid helper can use it. --- src/libutil/util.cc | 47 +++++++++++++++++++++++++++++++++++++++++++++++ src/libutil/util.hh | 5 +++++ 2 files changed, 52 insertions(+) (limited to 'src/libutil') diff --git a/src/libutil/util.cc b/src/libutil/util.cc index ae5fe821e78b..5907adc80718 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -707,6 +707,53 @@ void Pid::setSeparatePG(bool separatePG) } +void killUser(uid_t uid) +{ + debug(format("killing all processes running under uid `%1%'") % uid); + + assert(uid != 0); /* just to be safe... */ + + /* The system call kill(-1, sig) sends the signal `sig' to all + users to which the current process can send signals. So we + fork a process, switch to uid, and send a mass kill. */ + + Pid pid; + pid = fork(); + switch (pid) { + + case -1: + throw SysError("unable to fork"); + + case 0: + try { /* child */ + + if (setuid(uid) == -1) abort(); + + while (true) { + if (kill(-1, SIGKILL) == 0) break; + if (errno == ESRCH) break; /* no more processes */ + if (errno != EINTR) + throw SysError(format("cannot kill processes for uid `%1%'") % uid); + } + + } catch (std::exception & e) { + std::cerr << format("killing processes beloging to uid `%1%': %1%\n") + % uid % e.what(); + quickExit(1); + } + quickExit(0); + } + + /* parent */ + if (pid.wait(true) != 0) + throw Error(format("cannot kill processes for uid `%1%'") % uid); + + /* !!! We should really do some check to make sure that there are + no processes left running under `uid', but there is no portable + way to do so (I think). The most reliable way may be `ps -eo + uid | grep -q $uid'. */ +} + ////////////////////////////////////////////////////////////////////// diff --git a/src/libutil/util.hh b/src/libutil/util.hh index b88508dec30d..b850ee798c7c 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -224,6 +224,11 @@ public: }; +/* Kill all processes running under the specified uid by sending them + a SIGKILL. */ +void killUser(uid_t uid); + + /* Run a program and return its stdout in a string (i.e., like the shell backtick operator). */ string runProgram(Path program); -- cgit 1.4.1