--- /tmp/policyd-weight-0.1.14-beta.orig/debian/policyd-weight/usr/sbin/policyd-weight 2008-03-28 10:34:26.000000000 +0100 +++ /tmp/policyd-weight-0.1.14-beta/debian/policyd-weight/usr/sbin/policyd-weight 2008-03-28 15:49:41.922551492 +0100 @@ -247,6 +247,7 @@ } use Fcntl; +use File::Spec; use Sys::Syslog qw(:DEFAULT setlogsock); use Net::DNS; use Net::DNS::Packet qw(dn_expand); @@ -592,6 +593,12 @@ $conf_str = ""; +# +# check for nasty symlinks +# +check_symlnk('main: init:', + $LOCKPATH, $PIDFILE, $SPATH, "$LOCKPATH/cache_lock"); + # send HUP to kids if $RELOAD if($RELOAD) { @@ -2346,12 +2353,12 @@ } create_lockpath('cache'); - # grey magic to avoid races at startups + # avoid races at startups mkdir $LOCKPATH.'/cache_lock' or return undef; # check if a cache-socket file exist, and # whether we can connect to it. - if( -f $SPATH) + if( -S $SPATH) { my $test_sock = IO::Socket::UNIX->new($SPATH); return undef if ($test_sock && $test_sock->connected); @@ -2841,6 +2848,11 @@ mkdir $LOCKPATH or die "$who: error while creating $LOCKPATH: $!"; } + # + # check LOCKPATH, SPATH and cache_lock for being part of symlinks + # + check_symlnk( $who, $LOCKPATH, $SPATH, "$LOCKPATH/cache_lock" ); + my $tuid = $USER; if($USER =~ /[^0-9]/) @@ -2860,6 +2872,56 @@ } } +# +# usage: check_symlnk($caller, @files) +# +# caller: context specifier (eg: "cache: function:") +# files: list of files to check +sub check_symlnk +{ + my $who = shift; + for ( @_ ) + { + my $file = File::Spec->canonpath($_); + + my @stat = lstat( $file ); + + if(! -e _) + { + next; + } + + # first, file must not be a symlink + if ( -l _ ) + { + fatal_exit("$who: $file is a symbolic link. Symbolic links are not expected and not allowed within policyd-weight. Exiting!"); + } + + # second, file must be owned by uid root or $USER and + # gid root/wheel or $USER + if(!( + ( + $stat[4] == getpwnam($USER) || + $stat[4] == "0" + ) && + ( + $stat[5] == getgrnam($GROUP) || + $stat[5] == "0" + ) + ) + ) + { + fatal_exit("$who: $file is owned by UID $stat[4], GID $stat[5]. Exiting!"); + } + + # second the file/dir must not be world writeable + if(sprintf("%04o",$stat[2]) =~ /(7|6|3|2)$/) + { + fatal_exit("$who: $file is world writeable. Exiting!"); + } + } +} + # function for sanitizing floating point output sub myrnd {