Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 25 May 2013 16:46:47 +0300
From:      Johan Myreen <jem@iki.fi>
To:        freebsd-cvsweb@FreeBSD.org
Subject:   Bug related to ACLs in cvsweb
Message-ID:  <51A0C0C7.4080104@iki.fi>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------000904040501080507090103
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit

Hi.

Due to a Perl misfeature, cvsweb.cgi does not work correctly if Access 
Control Lists (ACLs) are in use. The script includes the pragma

use filetest qw(access);

This pragma changes how Perl does permission checks on files and 
directories; instead of using stat(), permissions are checked using 
access(). The problem is that the script uses the cached value of a 
stat() call to check permissions, using the special filehandle _.

When the filetest 'access' pragma is in use, the -r $file, -w $file and 
-x $file tests do not set the cache (because no call to stat() is made). 
What's worse, when the stat cache is set, e.g. as a result of -d $file, 
it contains the wrong value for a -r _ test. The stat cache contains the 
traditional rwx mode bits, and does not reflect any additional 
permissions granted by the ACL. See: http://perldoc.perl.org/filetest.html

ACLs are very useful when used with cvsweb. You can grant the 'www-data' 
user read permission to the repository files without opening them up to 
all users on the server (with chmod o+r). Of course, you could add user 
'www-data' to the 'cvs' group, but that would mean 'www-data' would have 
write permission to the repository.

Patch attached.

Keywords: cvsweb acl bug filetest access

Johan Myréen
jem@iki.fi


--------------000904040501080507090103
Content-Type: text/x-patch;
 name="cvsweb.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="cvsweb.diff"

diff -u cvsweb-3.0.6-orig/cvsweb.cgi cvsweb-3.0.6/cvsweb.cgi
--- cvsweb-3.0.6-orig/cvsweb.cgi	2005-09-25 23:28:51.000000000 +0300
+++ cvsweb-3.0.6/cvsweb.cgi	2013-05-25 15:01:58.000000000 +0300
@@ -990,10 +990,11 @@
     next if ($input{hidecvsroot} && $where eq '/' && $file eq 'CVSROOT');
 
     # Is it a directory?
-    my $isdir = -d catdir($fullname, $file);
+    my $subdir = catdir($fullname, $file);
+    my $isdir = -d $subdir;
 
     # Ignore non-readable files and directories?
-    next if ($input{hidenonreadable} && (! -r _ || ($isdir && ! -x _)));
+    next if ($input{hidenonreadable} && (! -r $subdir || ($isdir && ! -x $subdir)));
 
     my $attic = '';
     if ($file =~ s|^Attic/||) {
@@ -1459,8 +1460,8 @@
       ($filename) =
         (catfile($dirname, $filename) =~ VALID_PATH) or next; # untaint
       my ($file) = catfile($fullname, $filename);
-      next if ($filename !~ /,v$/o || !-f $file || !-r _);
-      my $modtime = -M _;
+      next if ($filename !~ /,v$/o || !-f $file || !-r $file);
+      my $modtime = -M $file;
       if (!defined($lastmod) || $modtime < $lastmodtime) {
         ($lastmod    = $filename) =~ s/,v$//;
         $lastmodtime = $modtime;
@@ -1718,7 +1719,7 @@
   my ($command) = @_;
   for my $d (@command_path) {
     my $cmd = catfile($d, $command);
-    return $cmd if (-x $cmd && !-d _);
+    return $cmd if (-x $cmd && !-d $cmd);
   }
   return '';
 }
@@ -1753,7 +1754,7 @@
   my $mimetype = $MTYPES{$suffix};
   $mimetype  ||= $MimeTypes->mimeTypeOf($fullname) if defined($MimeTypes);
 
-  if (!$mimetype && $suffix ne '*' && -f $mime_types && -r _) {
+  if (!$mimetype && $suffix ne '*' && -f $mime_types && -r $mime_types) {
     my $fh = do { local (*FH); };
     if (open($fh, $mime_types)) {
       my $re = sprintf('^\s*(\S+\/\S+)\s.+\b%s\b', quotemeta($suffix));
@@ -2454,7 +2455,7 @@
     # Note: last modified files from subdirs returned by
     # findLastModifiedSubdirs() come without the ,v suffix so they're not
     # found here, but have already been checked for readability.  *cough*
-    if (-r $files[$i] || !-e _) {
+    if (-r $files[$i] || !-e $files[$i]) {
       $i++;
     } else {
       push(@unreadable, splice(@files, $i, 1));

--------------000904040501080507090103--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?51A0C0C7.4080104>