From: "Roger Willcocks" <roger@filmlight.ltd.uk>
To: Timothy Shimmin <tes@sgi.com>
Cc: xfs@oss.sgi.com
Subject: Re: bug: truncate to zero + setuid
Date: Sun, 4 Nov 2007 11:59:51 -0000 [thread overview]
Message-ID: <000001c81f3e$eff344b0$6501a8c0@BODDINGTON> (raw)
In-Reply-To: 472A7940.5070800@sgi.com
[-- Attachment #1: Type: text/plain, Size: 1110 bytes --]
Timothy Shimmin wrote:
> Hi Roger,
>
...
> I don't like all these inconsistencies.
Take a look at the attached patch relative to the current cvs (it's a bit
big to put
inline). The basic problem is it's currently unclear when to set the times
from
va_atime etc. and when to set them to the current time. So I've used the
already
defined XFS_AT_UPDxTIME flags to indicate that a time should be set to 'now'
and XFS_AT_xTIME to mean set it using va_xtime. This seems to fit well with
the current code and I wonder if that's how it was meant to work in the
first
place. I've also removed the now redundant ATTR_UTIME flag and pulled
the null truncate to the top, which simplifies things.
One query: in both xfs_iops.c/xfs_vn_setattr and
xfs_dm.c/xfs_dm_set_fileattr the
ATIME branch sets the inode's atime directly. This is probably something to
do with
the comment above xfs_iops.c/xfs_ichgtime ('to make sure the access time
update
will take') but it could probably be handled better.
> BTW, your locking looks wrong - it appears you don't unlock when the
> file is non-zero size.
Oops...
--
Roger
[-- Attachment #2: xfs_setattr.patch --]
[-- Type: application/octet-stream, Size: 5478 bytes --]
diff -ur xfs.orig/linux-2.6/xfs_iops.c xfs/linux-2.6/xfs_iops.c
--- xfs.orig/linux-2.6/xfs_iops.c 2007-11-04 10:59:00.923480296 +0000
+++ xfs/linux-2.6/xfs_iops.c 2007-11-04 12:43:15.702609336 +0000
@@ -655,13 +655,21 @@
vattr.va_size = attr->ia_size;
}
if (ia_valid & ATTR_ATIME) {
- vattr.va_mask |= XFS_AT_ATIME;
- vattr.va_atime = attr->ia_atime;
- inode->i_atime = attr->ia_atime;
+ if (ia_valid & ATTR_ATIME_SET) {
+ vattr.va_mask |= XFS_AT_ATIME;
+ vattr.va_atime = attr->ia_atime;
+ inode->i_atime = attr->ia_atime;
+ } else {
+ vattr.va_mask |= XFS_AT_UPDATIME;
+ }
}
if (ia_valid & ATTR_MTIME) {
- vattr.va_mask |= XFS_AT_MTIME;
- vattr.va_mtime = attr->ia_mtime;
+ if (ia_valid & ATTR_MTIME_SET) {
+ vattr.va_mask |= XFS_AT_MTIME;
+ vattr.va_mtime = attr->ia_mtime;
+ } else {
+ vattr.va_mask |= XFS_AT_UPDMTIME;
+ }
}
if (ia_valid & ATTR_CTIME) {
vattr.va_mask |= XFS_AT_CTIME;
@@ -674,8 +682,6 @@
inode->i_mode &= ~S_ISGID;
}
- if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET))
- flags |= ATTR_UTIME;
#ifdef ATTR_NO_BLOCK
if ((ia_valid & ATTR_NO_BLOCK))
flags |= ATTR_NONBLOCK;
diff -ur xfs.orig/linux-2.6/xfs_vnode.h xfs/linux-2.6/xfs_vnode.h
--- xfs.orig/linux-2.6/xfs_vnode.h 2007-11-04 10:59:00.923480296 +0000
+++ xfs/linux-2.6/xfs_vnode.h 2007-11-04 11:01:33.338309720 +0000
@@ -270,7 +270,6 @@
/*
* Flags to vop_setattr/getattr.
*/
-#define ATTR_UTIME 0x01 /* non-default utime(2) request */
#define ATTR_DMI 0x08 /* invocation from a DMI function */
#define ATTR_LAZY 0x80 /* set/get attributes lazily */
#define ATTR_NONBLOCK 0x100 /* return EAGAIN if operation would block */
diff -ur xfs.orig/xfs_vnodeops.c xfs/xfs_vnodeops.c
--- xfs.orig/xfs_vnodeops.c 2007-11-04 10:59:00.917481208 +0000
+++ xfs/xfs_vnodeops.c 2007-11-04 12:07:44.917537904 +0000
@@ -214,10 +214,10 @@
{
bhv_vnode_t *vp = XFS_ITOV(ip);
xfs_mount_t *mp = ip->i_mount;
- xfs_trans_t *tp;
+ xfs_trans_t *tp = NULL;
int mask;
int code;
- uint lock_flags;
+ uint lock_flags=0;
uint commit_flags=0;
uid_t uid=0, iuid=0;
gid_t gid=0, igid=0;
@@ -244,21 +244,51 @@
if (XFS_FORCED_SHUTDOWN(mp))
return XFS_ERROR(EIO);
+ olddquot1 = olddquot2 = NULL;
+ udqp = gdqp = NULL;
+
+ /*
+ * Truncate is special because it changes the file as well as
+ * the attributes.
+ */
+ if (mask & XFS_AT_SIZE) {
+ /* Must have write permission and not be a directory. */
+ if (VN_ISDIR(vp)) {
+ code = XFS_ERROR(EISDIR);
+ goto error_return;
+ } else if (!VN_ISREG(vp)) {
+ code = XFS_ERROR(EINVAL);
+ goto error_return;
+ }
+ /*
+ * Short circuit the truncate case for zero length files.
+ */
+ if (vap->va_size == 0) {
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
+ if ((ip->i_size == 0) && (ip->i_d.di_nextents == 0)) {
+ mask |= XFS_AT_UPDCTIME|XFS_AT_UPDMTIME;
+ mask &= ~XFS_AT_SIZE;
+ }
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+ }
+ }
+
/*
* Timestamps do not need to be logged and hence do not
* need to be done within a transaction.
*/
if (mask & XFS_AT_UPDTIMES) {
- ASSERT((mask & ~XFS_AT_UPDTIMES) == 0);
timeflags = ((mask & XFS_AT_UPDATIME) ? XFS_ICHGTIME_ACC : 0) |
((mask & XFS_AT_UPDCTIME) ? XFS_ICHGTIME_CHG : 0) |
((mask & XFS_AT_UPDMTIME) ? XFS_ICHGTIME_MOD : 0);
- xfs_ichgtime(ip, timeflags);
- return 0;
+ mask &= ~XFS_AT_UPDTIMES;
}
- olddquot1 = olddquot2 = NULL;
- udqp = gdqp = NULL;
+ if (mask == 0) {
+ if (timeflags && !(flags & ATTR_DMI))
+ xfs_ichgtime(ip, timeflags);
+ return 0;
+ }
/*
* If disk quotas is on, we make sure that the dquots do exist on disk,
@@ -307,12 +337,11 @@
* For the other attributes, we acquire the inode lock and
* first do an error checking pass.
*/
- tp = NULL;
lock_flags = XFS_ILOCK_EXCL;
if (flags & ATTR_NOLOCK)
need_iolock = 0;
if (!(mask & XFS_AT_SIZE)) {
- if ((mask != (XFS_AT_CTIME|XFS_AT_ATIME|XFS_AT_MTIME)) ||
+ if ((mask & ~(XFS_AT_CTIME|XFS_AT_ATIME|XFS_AT_MTIME)) != 0 ||
(mp->m_flags & XFS_MOUNT_WSYNC)) {
tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE);
commit_flags = 0;
@@ -451,24 +480,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;
- } else if (!VN_ISREG(vp)) {
- code = XFS_ERROR(EINVAL);
- goto error_return;
- }
/*
* Make sure that the dquots are attached to the inode.
*/
@@ -481,8 +492,7 @@
*/
if (mask & (XFS_AT_ATIME|XFS_AT_MTIME)) {
if (!file_owner) {
- if ((flags & ATTR_UTIME) &&
- !capable(CAP_FOWNER)) {
+ if (!capable(CAP_FOWNER)) {
code = XFS_ERROR(EPERM);
goto error_return;
}
@@ -760,7 +770,7 @@
timeflags &= ~XFS_ICHGTIME_MOD;
timeflags |= XFS_ICHGTIME_CHG;
}
- if (tp && (flags & ATTR_UTIME))
+ if (tp)
xfs_trans_log_inode (tp, ip, XFS_ILOG_CORE);
}
next prev parent reply other threads:[~2007-11-05 0:01 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
2007-10-30 17:28 ` Roger Willcocks
2007-11-02 1:11 ` Timothy Shimmin
2007-11-04 11:59 ` Roger Willcocks [this message]
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='000001c81f3e$eff344b0$6501a8c0@BODDINGTON' \
--to=roger@filmlight.ltd.uk \
--cc=tes@sgi.com \
--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