public inbox for linux-xfs@vger.kernel.org
 help / color / mirror / Atom feed
From: Timothy Shimmin <tes@sgi.com>
To: Roger Willcocks <roger@filmlight.ltd.uk>
Cc: xfs@oss.sgi.com
Subject: Re: bug: truncate to zero + setuid
Date: Tue, 30 Oct 2007 15:06:06 +1100	[thread overview]
Message-ID: <4726ADAE.9070206@sgi.com> (raw)
In-Reply-To: <47262CD0.5010708@filmlight.ltd.uk>

Roger Willcocks wrote:
> Tim Shimmin wrote:
>> Hi Roger,
>>
>> Roger Willcocks wrote:
>>> The nfsv3 setattr call permits a simultaneous truncate + setuid/gid 
>>> operation. Normally XFS handles this fine, but if the file's being 
>>> truncated to zero, and the file's already empty, XFS simply ignores 
>>> the setuid/gid part, returning 'success'.
>>>
>>> The error's in xfs_vnodeops.c/xfs_setattr below the comment 'Short 
>>> circuit the truncate case for zero length files', which bypasses all 
>>> other changes.
>>>
>>> The simplest fix is to test whether this is the only change that's 
>>> happening, otherwise you get tangled in transactions.
>>>
>>>        if (mask & XFS_AT_SIZE) {
>>>                /* Short circuit the truncate case for zero length 
>>> files */
>>> -               if ((vap->va_size == 0) &&
>>> +               if (((mask & ~XFS_AT_SIZE) == 0) && (vap->va_size == 
>>> 0) &&
>>>                   (ip->i_d.di_size == 0) && (ip->i_d.di_nextents == 
>>> 0)) {
>>>
>>>
>>> -- 
>>> Roger
>>>
>>
>> Yeah, I see your problem.
>> It is interesting to know how much of multiple actions (different
>> bits of mask) are supported.
>> XFS_AT_UPDTIMES doesn't support anything else and will return quickly.
>> As far as code which goes via error_return, it looks like the
>> only non-error case is the short-circuit one mentioned above -
>> truncating to zero an already zeroed file.
>>
>> I see your fix will get what we want although, it will mean that we
>> will go thru the truncating path when we don't need to.
>> It would be nice if we could act like the XFS_AT_SIZE was never set
>> on the call in the case that other bits are set.
>> Though when we first test the AT_SIZE, we don't have the inode locked.
>> And I presume in that case we don't necessarily need to send a
>> DMAPI truncate event?
>> So I wonder if before the 1st AT_SIZE test that we have now,
>> in the AT_SIZE case and with other bits set,
>> we could lock the inode and test
>> for the zero truncate of zero-len file and if so then remove the 
>> AT_SIZE bit
>> and then go on to the other testing as if AT_SIZE was never set.
>> Hmmm, may be that just complicates things too much.
>>
> Yes I looked at simply unsetting the XFS_AT_SIZE bit (you'd also need to 
> set
> timeflags appropriately) but the problem is the bit's used to check when 
> to create
> a transaction - either up front as  XFS_TRANS_SETATTR_NOT_SIZE, or
> later on, after the inode's been locked and unlocked again, as
> XFS_TRANS_SETATTR_SIZE. So if you unset the bit (and there's still more
> to do) you need to build a not_size transaction, at which point you 
> might as well
> rewrite the whole routine...
> 
> -- 
> Roger

So this was done by Steve L. for AIM performance...

----------------------------
revision 1.446
date: 2000/06/09 02:59:45;  author: lord;  state: Exp;  lines: +11 -0
modid: 2.4.0-test1-xfs:slinx:55891a
Merge of 2.3.99pre2-xfs:slinx:55891a by ananth.

   Short circuit the case where we truncate a zero length
   file down to zero length so that we do not do a transaction.
   This close to doubles create/close AIM run performance.
----------------------------

 > p_rdiff -r1.445,1.446 xfs_vnodeops.c
746a747,757
 >               /* Short circuit the truncate case for zero length files */
 >               if ((vap->va_size == 0) &&
 >                  (ip->i_d.di_size == 0) && (ip->i_d.di_nextents == 0)) {
 >                       xfs_iunlock(ip, XFS_ILOCK_EXCL);
 >                       lock_flags &= ~XFS_ILOCK_EXCL;
 >                       if (mask & AT_CTIME)
 >                               xfs_ichgtime(ip, XFS_ICHGTIME_CHG);
 >                       code = 0;
 >                       goto error_return;
 >               }
 >


----------------------------
revision 1.506
date: 2001/06/26 22:07:29;  author: lord;  state: Exp;  lines: +1 -1
modid: 2.4.x-xfs:slinx:97694a
Set the mtime on a zero length file when a create is being done on
top of it.
----------------------------

 > p_rdiff -r1.505,1.506 xfs_vnodeops.c
526c526
<                               xfs_ichgtime(ip, XFS_ICHGTIME_CHG);
---
 >                               xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);




I presume it was done where it was done so that the inode was locked and we
were under the XFS_AT_SIZE predicate.

I was just thinking of something like...
but I'm probably missing something.

Index: 2.6.x-xfs/fs/xfs/xfs_vnodeops.c
===================================================================
--- 2.6.x-xfs.orig/fs/xfs/xfs_vnodeops.c        2007-10-12 16:06:15.000000000 +1000
+++ 2.6.x-xfs/fs/xfs/xfs_vnodeops.c     2007-10-30 14:59:46.418837757 +1100
@@ -304,6 +304,24 @@
         }

         /*
+        * Short circuit the truncate case for zero length files.
+        * If more mask bits are set, then just remove the SIZE one
+        * and keep going.
+        */
+       if (mask & XFS_AT_SIZE) {
+               xfs_ilock(ip, XFS_ILOCK_SHARED);
+               if ((vap->va_size == 0) && (ip->i_size == 0) && (ip->i_d.di_nextents == 0)) {
+                       if (mask & ~XFS_AT_SIZE) {
+                               mask &= ~XFS_AT_SIZE;
+                       } else {
+                               xfs_iunlock(ip, XFS_ILOCK_SHARED);
+                               return 0;
+                       }
+               }
+               xfs_iunlock(ip, XFS_ILOCK_SHARED);
+       }
+
+       /*
          * For the other attributes, we acquire the inode lock and
          * first do an error checking pass.
          */
@@ -451,17 +469,6 @@
          * Truncate file.  Must have write permission and not be a directory.
          */
         if (mask & XFS_AT_SIZE) {
-               /* Short circuit the truncate case for zero length files */
-               if ((vap->va_size == 0) &&
-                  (ip->i_size == 0) && (ip->i_d.di_nextents == 0)) {
-                       xfs_iunlock(ip, XFS_ILOCK_EXCL);
-                       lock_flags &= ~XFS_ILOCK_EXCL;
-                       if (mask & XFS_AT_CTIME)
-                               xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
-                       code = 0;
-                       goto error_return;
-               }
-
                 if (VN_ISDIR(vp)) {
                         code = XFS_ERROR(EISDIR);
                         goto error_return;

  reply	other threads:[~2007-10-30  4:06 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-10-28 14:36 bug: truncate to zero + setuid Roger Willcocks
2007-10-29  0:54 ` Tim Shimmin
2007-10-29 18:56   ` Roger Willcocks
2007-10-30  4:06     ` Timothy Shimmin [this message]
2007-10-30 17:28       ` Roger Willcocks
2007-11-02  1:11         ` Timothy Shimmin
2007-11-04 11:59           ` Roger Willcocks
2007-11-08  3:13             ` Timothy Shimmin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4726ADAE.9070206@sgi.com \
    --to=tes@sgi.com \
    --cc=roger@filmlight.ltd.uk \
    --cc=xfs@oss.sgi.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox