# HG changeset patch # User Eris Caffee # Date 1305626454 18000 # Node ID 1217ea1da6d7b1fa6e964a6a44f9046a216a7126 # Parent c1b3644bfc0462d0f861d54ebb324320dfe80f99 Ready for testing. diff -r c1b3644bfc04 -r 1217ea1da6d7 rm-limit.pl --- a/rm-limit.pl Mon May 09 20:15:10 2011 -0500 +++ b/rm-limit.pl Tue May 17 05:00:54 2011 -0500 @@ -18,7 +18,36 @@ # along with this program. If not, see . # ################################################################################ - +# +# A limited rm wrapper. +# +# This scripts has 3 lists: +# A blacklist of directories from which this script will absolutely refuse +# to delete anything. +# A whitelist of directories from which deletions are always allowed. +# A whitelist of directories from which deletions are always allowed only if +# they occur in subdirectories of the listed main directory. +# +# Any file not specified as whitelisted or blacklisted will generate a +# warning prompt and offer the user a chance to cancel the deletion. +# +# The purpose is to help prevent accidental deletion of important system files. +# +# To use this, install this script somewher ein your path and add something +# like the following to your default login scripts, such as the .bash_profile +# file of the root user. +# +# alias | grep -q "alias rm=" +# if [ $? -eq 0 ] ; then +# RM_Opts=$(alias | awk '/alias rm=/ { sub(/^rm /, "", $2); print $2}' FS="'") +# fi +# +# unalias rm 2> /dev/null +# alias rm="rm-limit ${RM_Opts}" +# +# By installing this as an alias for rm that is set up in .bash_profile, it will +# only be active during interactive logins, and not when scripts are running. +# use strict; use warnings; @@ -27,16 +56,13 @@ use File::Basename; -my $debug = 1; - -# Any file not in either the whitelist of the blacklist will generate a warning -# asking the user to confirm the command before proceeding. - ################################################################################ # # Note: / itself is protected by default. You are not allowed to delete the # entire filesystem using this script no matter what. # +# Protecting or exposing a directory affects all subdirectories underneath it. +# # The whitelist consists of directories from which we may always delete. my @whitelist = ( @@ -59,13 +85,21 @@ my @blacklist = ( '/bin/', + '/boot', '/etc', '/lib/', - '/boot', + '/lib64', + '/sbin', ); ################################################################################ +my $debug = 0; + +my $rm="/bin/rm"; +my $echo="/bin/echo"; + + my $proceed = "yes"; my $fail = 0; my $file = 0; @@ -83,6 +117,10 @@ next; } + if (check_whitelist_subdirs($path) ) { + next; + } + $proceed = "no"; if (check_blacklist($path)) { @@ -117,9 +155,14 @@ $proceed = ; } +chomp($proceed); if ($proceed eq "yes"){ - exec('/usr/bin/echo', ('/bin/rm', @ARGV)); -} + if ($debug) { + exec($echo, ($rm, @ARGV)); + } else { + exec($rm, @ARGV); + } +} ################################################################################ # Expand to full paths, append / to ends of directories. @@ -174,13 +217,14 @@ my $path = normalize_name($_); for (my $i = 0; $i <= $#whitelist_subdirs; $i += 1) { $regex = "^".quotemeta($whitelist_subdirs[$i]); - if ($whitelist_subdirs[$i] !~ m{/$}) { - $regex = $regex."$$"; - } ($debug) and print("regex is $regex\n"); if (($path =~ $regex) and ($path ne $whitelist_subdirs[$i])) { - $debug and print("Whitelisted for being in $whitelist_subdirs[$i]: $_\n"); - return 1; + $regex = $regex.".*/.+"; + ($debug) and print("new regex is $regex\n"); + if ($path =~ $regex) { + $debug and print("Whitelisted for being subdir of $whitelist_subdirs[$i]: $_\n"); + return 1; + } } } @@ -225,8 +269,10 @@ $whitelist[$i] = $whitelist[$i]."/"; } } + + # All entries on the whitelist_subdirs list _must_ be directories. for (my $i = 0; $i <= $#whitelist_subdirs; $i += 1) { - if (-d $whitelist_subdirs[$i] and $whitelist_subdirs[$i] !~ m{/$}) { + if ($whitelist_subdirs[$i] !~ m{/$}) { $whitelist_subdirs[$i] = $whitelist_subdirs[$i]."/"; } }