sukill: Stopping Unruly Processes
Steven G. Isaacson
A runaway process on a small system isn't much of a
problem: it's
easy enough to identify the guilty process and its owner
and have
either the owner or a user with the root password "fix"
the
problem.
On a large system with dozens or hundreds of users,
a more formal
approach is required. In this case, what's needed is
a tool that allows
an ordinary user to kill another user's process without
compromising
system security.
The kill Command
Processes can be stopped with the kill command.
kill [ -signal ] pid ...
The kill command sends a signal to the specified process-id
(you determine the correct process-id using the ps
command).
Many different signals may be sent to a process -- the
hangup signal,
interrupt, quit, exceeded CPU time limit, floating point
exception,
kill, bus error, segmentation violation, user-defined
signal, death
of a child -- but the two signals most commonly sent
are: software
termination (signal 15) and kill (signal 9). These two
are defined
in /usr/include/sys/signal.h as SIGTERM and SIGKILL.
SIGTERM is the default signal sent by kill. It provides
a warning that can be caught by the process and thus
be dealt with
or ignored. vi, for example, catches the signal and
then cleans
up its temporary files before exiting.
SIGKILL, however, cannot be caught or ignored. It terminates
the process immediately.
The problem with the kill command is that it requires
super
user provileges to kill a process other than your own.
To make it
generally available, you could choose to create a set-uid
root copy
of the command (i.e., /bin/kill).
A set-uid program temporarily changes the effective
user id of whoever
is running the program. If the user id is set to root,
any user who
runs the program has root privileges.
Thus if you make kill a set-uid root program, the user
will
temporarily acquire root privileges and will be able
to kill any process
on the system.
Set-uid programs are potentially dangerous, however,
and should generally
be avoided. In the case of the kill command, any user
may kill
any other user's process and no one would be the wiser;
moreover,
any user (when running as root) could bring down the
system by killing
pid -1.
sukill provides a better way to stop unruly processes.
sukill [ -signal ] pid ...
sukill is similar to the kill command except
that it allows you to kill processes other than your
own. It does
not, however, automatically give every user on the system
the power
to kill.
sukill Safeguards
sukill has three safeguards: it restricts the range
of the
process-ids that can be killed; it can be used with
"allow"
and "deny" files; and it logs an audit trail.
Restricted PIDs
sukill does not allow you to kill a process-id less
than 100.
This prevents users from inadvertently (or intentionally)
bringing
down the system, which could happen if they're allowed
to kill system
processes.
One hundred is a happy medium between the system processes
that are
started at boot time -- for example, init, sendmail,
and cron -- and user processes. The ability to kill
system
processes should be left to the system administrator.
If this value
is too high or too low, you can easily change it.
Allow and Deny
sukill can be used with "allow" and "deny"
files. These are files that contain a list of users
who are allowed
or denied access to sukill.
To permit specific users to run sukill, add their lognames
to the sukill.allow file. To deny particular users,
add their
lognames to sukill.deny.
If neither sukill.allow nor sukill.deny exists, then
every user has permission to execute sukill. If you
do use
these files, set their permissions so that only root
can write to
them.
In practice the allow and deny files are seldom used,
mainly
because of sukill's verbose logging. However, different
sites
have different requirements, and you may find that allow
and
deny files are appropriate.
Logging
sukill writes the following information to the log file:
logname,
sukill command-line arguments (the optional signal level
and
the pid(s) to be killed); system date and time; logname
(again), user
id, group id, effective user id (always 0 unless sukill
is not installed
correctly), effective group id, current user id name,
current working
directory, values of $HOME and $NAME environment variables;
and finally the results of a verbose listing from /bin/ps
for
the specified pid(s).
The output from /bin/ps is exactly what you would expect
a
"reasonable user" to look at before killing
someone else's
process. In fact you must use the ps command to obtain
the
pid number. Figure 1 shows a sample logfile entry.
The entry reveals that a process owned by sneed was
killed by jamesy
and that jamesy used -9, the SIGKILL signal. The file
also
shows that the process that was killed had no controlling
tty
and had been going for three hours and two minutes.
The log file is not pretty and is seldom examined, but
if a problem
does occur -- a user's program keeps stopping unexpectedly,
say
-- it provides an audit trail.
Source Code
Listing 1 contains all of the source for sukill. Simply
compile
it, change the owner to root, and change the permissions
to 4755.
The logging section may have to be customized for your
system. It
could be made less verbose or could perhaps have installation-specific
requirements added to it.
sukill is a simple and safe way to give more power to
the user.
You may even find that you use it yourself instead of
always having
to su to root in order to kill a process.
About the Author
Steven G. Isaacson has been writing C and Informix
4GL applications
since 1985. He is currently developing automated testing
tools for
FourGen Software, the leading developer of accounting
software and
CASE Tools for the UNIX market. He may be reached via
email at
uunet!4gen!steve1 or steve1%4gen@uunet.uu.net.
|