#!/usr/bin/perl -w # Copyright © 2001, 2002, 2003, 2004, 2005 Jamie Zawinski # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation. No representations are made about the suitability of this # software for any purpose. It is provided "as is" without express or # implied warranty. # # Created: 9-Jun-2001 # # This script kills any processes owned by the "guest" user that don't match # a list of "allowed" executables. This is not so much for security reasons, # as for cleanliness: if we run this script when the screensaver activates, # we can kill off any apps that other users have left cluttering up the # screen. # require 5; use diagnostics; use strict; my $progname = $0; $progname =~ s@.*/@@g; my $version = q{ $Revision: 1.15 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/; my $verbose = 0; my $debug = 0; my $target_owner = "guest"; my $process_death_grace_period = 2; # seconds between SIGTERM and SIGKILL # This is the list of programs we won't kill, by full executable pathname. # Elements can also be directories, in which case they match all executables # in that directory. # my %allowed_programs = ( "/ro/bin/tcsh" => 1, "/ro/bin/bash" => 1, "/ro/bin/sleep" => 1, "/ro/bin/cat" => 1, "/ro/bin/sed" => 1, "/ro/usr/bin/perl" => 1, "/ro/usr/bin/gnome-name-service" => 1, "/ro/usr/bin/gnome-panel" => 1, "/ro/usr/bin/gnome-settings-daemon" => 1, "/ro/usr/bin/metacity" => 1, "/ro/usr/libexec/bonobo-activation-server" => 1, "/ro/usr/libexec/gconfd-2" => 1, "/ro/usr/libexec/multiload-applet-2" => 1, "/ro2/home/local/bin/chbg" => 1, "/ro/usr/lib/firefox-1.0/firefox-bin" => 1, "/ro/usr/bin/xscreensaver" => 1, "/ro/usr/libexec/xscreensaver/" => 1, # whole directory "/ro/usr/bin/xscreensaver-getimage" => 1, "/ro/usr/bin/xscreensaver-getimage-file" => 1, ); # These are programs that we kill, but that we don't bother logging, # since we're a-killin' them all the time... # my %boring_programs = ( "/ro/usr/bin/gaim" => 1, "/ro/usr/bin/xchat" => 1, "/ro/usr/bin/gsendmail" => 1, "/ro/usr/bin/gnome-terminal" => 1, # "/ro/usr/bin/gaim_applet" => 1, # "/ro/usr/bin/aspell" => 1, # "/ro/usr/bin/gnomeicu" => 1, ); sub error { ($_) = @_; print STDERR "$progname: $_\n"; exit 1; } my %pid_names = (); # returns a list of pids that we have marked for death # sub get_pids { my @pids = (); my $target_owner_id = getpwnam($target_owner); error ("no user id number for $target_owner?") unless ($target_owner_id); foreach () { my $file = $_; my ($pid) = m@/(\d+)/exe$@; next unless $pid; my @st = lstat($file); my $owner = $st[4]; next unless defined($owner); my $ok = ($owner == $target_owner_id); if (!$ok && $verbose > 2) { print STDERR "$progname: pid $pid skipping (owner: " . getpwuid($owner) . ")\n"; } next unless ($ok); my $exe = readlink($file); next unless defined($exe); $ok = defined($allowed_programs{$exe}); if (!$ok) { # if the executable didn't match, check the excutable's directory. my $dir = $exe; $dir =~ s@/[^/]+$@/@; $ok = defined($allowed_programs{$dir}); } if (!$ok) { $pid_names{$pid} = $exe; push (@pids, $pid); } elsif ($verbose > 1) { print STDERR "$progname: pid $pid: keeping $exe\n"; } } return sort (@pids); } sub kill_procs { my @pids = get_pids(); if ($#pids < 0) { print STDERR "$progname: nothing to kill\n" if ($verbose > 1); return; } if ($verbose) { foreach my $pid (@pids) { my $name = $pid_names{$pid} || "???"; print STDERR "$progname: killing $pid ($name)\n" if ($verbose > 1 || !$boring_programs{$name}); } } if (!$debug) { kill ('TERM', @pids); sleep $process_death_grace_period; kill ('KILL', @pids); } } sub usage { print STDERR "usage: $progname [--verbose] [--debug]\n"; exit 1; } sub main { while ($_ = $ARGV[0]) { shift @ARGV; if ($_ eq "--verbose") { $verbose++; } if ($_ eq "--debug") { $debug++; } elsif (m/^-v+$/) { $verbose += length($_)-1; } elsif (m/^-d+$/) { $debug += length($_)-1; } elsif (m/^-./) { usage; } else { usage; } } kill_procs(); } main; exit 0;