X-Recipient: archive-cygwin AT delorie DOT com X-Spam-Check-By: sourceware.org Date: Tue, 11 Aug 2009 09:00:46 +0200 From: Corinna Vinschen To: cygwin AT cygwin DOT com Subject: Re: Perl bug (was Re: [1.7] cygwin allows writing to readonly files) Message-ID: <20090811070045.GZ3204@calimero.vinschen.de> Reply-To: cygwin AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com References: <20090810132515 DOT GP3204 AT calimero DOT vinschen DOT de> <20090810164057 DOT GV3204 AT calimero DOT vinschen DOT de> <6910a60908101701m77bcb1b3x55e48d028bf35ef0 AT mail DOT gmail DOT com> <6910a60908101949k5f2ce354p1ccda7f2acd9927f AT mail DOT gmail DOT com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <6910a60908101949k5f2ce354p1ccda7f2acd9927f@mail.gmail.com> User-Agent: Mutt/1.5.19 (2009-02-20) Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com On Aug 11 04:49, Reini Urban wrote: > 2009/8/11 Reini Urban: > > 2009/8/10 Corinna Vinschen: > >> On Aug 10 20:11, Alexey Borzenkov wrote: > >>> Anyway, it means there is a bug in perl, because on Linux: > >>> > >>> root AT kitsu:~# touch test.txt > >>> root AT kitsu:~# chmod 0444 test.txt > >>> root AT kitsu:~# perl -e 'print "writable\n" if -w "test.txt"' > >>> writable > >>> > >>> On Cygwin 1.7 perl thinks that the file is not writable. > >> > >> Indeed.  Checking with strace I found that the test is the same on Linux > >> and Cygwin.  In both cases perl uses stat(), and the returned permissions > >> are the same (0444).  Further experimenting shows that perl has a > >> hardcoded uid == 0 test which must obviously fail on Cygwin.  If I change > >> the user's uid to 0, the string "writable" is printed by the above command. > >> > >> That's a bug in perl.  There are other OSes out there which have > >> root-like permissions for non-0 uids.  Perl should use the access() > >> function to check for read/write/execute permissions, which always > >> returns the correct result independent of the uid of the current user. > > > > Thanks. > > I'll carry it along to p5p, but it will definitely not appear in > > upstream 5.10.1 > > because this gate is already closed. > > Even a horrible performance problem with > > File::Spec::Cygwin::case_tolerant was not fixed. > > > > But I work on a fix to be included in blead and in my cygwin package. > > Bug confirmed too early. It's actually defined and described this way. > access() is not used for performance reasons. See perldoc perlfunc -X > > If you are using ACLs, there is a pragma called C that may > produce more accurate results than the bare stat() mode bits. > When under the C the above-mentioned filetests > will test whether the permission can (not) be granted using the > access() family of system calls. Also note that the C<-x> and C<-X> may > under this pragma return true even if there are no execute permission > bits set (nor any extra execute permission ACLs). This strangeness is > due to the underlying system calls' definitions. Note also that, due to > the implementation of C, the C<_> special > filehandle won't cache the results of the file tests when this pragma is > in effect. Read the documentation for the C pragma for more > information. As far as I'm concerned this is still a bug. It will result in different behaviour of the same script on different platforms for no apparent reason. > $ ./perl -e 'print "writable\n" if -w "test.txt"' > > $ ./perl -e 'use filetest "access"; print "writable\n" if -w "test.txt"' > writable > > I can turn on access checks easily for CYGWIN but cygwin perl is already > slow enough, so I will not do that. > > Changing the uid==0 check to check the Administrators gid is more promising. > i.e. > --- doio.c.orig 2009-04-18 19:17:04.000000000 +0200 > +++ doio.c 2009-08-11 04:46:09.343750000 +0200 > @@ -1918,7 +1918,11 @@ > return (mode & statbufp->st_mode) ? TRUE : FALSE; > > #else /* ! DOSISH */ > +# ifndef __CYGWIN__ > if ((effective ? PL_euid : PL_uid) == 0) { /* root is special */ > +# else > + if ((effective ? PL_egid : PL_gid) == 544) { /* member of > Administrators? */ > +# endif > if (mode == S_IXUSR) { > if (statbufp->st_mode & 0111 || S_ISDIR(statbufp->st_mode)) > return TRUE; > > but this didn't help me, because Administrators is not my first group. > So I call this a known limitation for all ACL aware filesystems. That might be a good workaround nevertheless. You should just test the list of supplementary groups as well, along these lines: # ifndef __CYGWIN__ if ((effective ? PL_euid : PL_uid) == 0) { /* root is special */ # else int is_admin = false; gid_t gid = effective ? PL_egid : PL_gid; int cnt, i; gid_t *glist; cnt = getgroups (0, NULL); if (cnt > 0) { glist = (gid_t *) malloc (cnt * sizeof (gid_t)); cnt = getgroups (cnt, glist); for (i = 0; i < cnt; ++i) if (gid == glist[i]) { is_admin = true; break; } free (glist); } if (is_admin) # endif Corinna -- Corinna Vinschen Please, send mails regarding Cygwin to Cygwin Project Co-Leader cygwin AT cygwin DOT com Red Hat -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple