Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 124953
b: refs/heads/master
c: c4cd747
h: refs/heads/master
i:
  124951: 50a56c5
v: v3
  • Loading branch information
Christoph Hellwig authored and Lachlan McIlroy committed Dec 11, 2008
1 parent 913586f commit 52424de
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 114 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 4d4be482a4d78ca906f45e99fd9fdb91e907f5ad
refs/heads/master: c4cd747ee6c3ba1e7727878e3fce482d0d8c0136
149 changes: 36 additions & 113 deletions trunk/fs/xfs/xfs_vnodeops.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ xfs_setattr(
gid_t gid=0, igid=0;
int timeflags = 0;
struct xfs_dquot *udqp, *gdqp, *olddquot1, *olddquot2;
int file_owner;
int need_iolock = 1;

xfs_itrace_entry(ip);
Expand All @@ -81,6 +80,10 @@ xfs_setattr(
if (XFS_FORCED_SHUTDOWN(mp))
return XFS_ERROR(EIO);

code = -inode_change_ok(inode, iattr);
if (code)
return code;

olddquot1 = olddquot2 = NULL;
udqp = gdqp = NULL;

Expand Down Expand Up @@ -158,56 +161,6 @@ xfs_setattr(

xfs_ilock(ip, lock_flags);

/* boolean: are we the file owner? */
file_owner = (current_fsuid() == ip->i_d.di_uid);

/*
* Change various properties of a file.
* Only the owner or users with CAP_FOWNER
* capability may do these things.
*/
if (mask & (ATTR_MODE|ATTR_UID|ATTR_GID)) {
/*
* CAP_FOWNER overrides the following restrictions:
*
* The user ID of the calling process must be equal
* to the file owner ID, except in cases where the
* CAP_FSETID capability is applicable.
*/
if (!file_owner && !capable(CAP_FOWNER)) {
code = XFS_ERROR(EPERM);
goto error_return;
}

/*
* CAP_FSETID overrides the following restrictions:
*
* The effective user ID of the calling process shall match
* the file owner when setting the set-user-ID and
* set-group-ID bits on that file.
*
* The effective group ID or one of the supplementary group
* IDs of the calling process shall match the group owner of
* the file when setting the set-group-ID bit on that file
*/
if (mask & ATTR_MODE) {
mode_t m = 0;

if ((iattr->ia_mode & S_ISUID) && !file_owner)
m |= S_ISUID;
if ((iattr->ia_mode & S_ISGID) &&
!in_group_p((gid_t)ip->i_d.di_gid))
m |= S_ISGID;
#if 0
/* Linux allows this, Irix doesn't. */
if ((iattr->ia_mode & S_ISVTX) && !S_ISDIR(ip->i_d.di_mode))
m |= S_ISVTX;
#endif
if (m && !capable(CAP_FSETID))
iattr->ia_mode &= ~m;
}
}

/*
* Change file ownership. Must be the owner or privileged.
*/
Expand All @@ -223,22 +176,6 @@ xfs_setattr(
gid = (mask & ATTR_GID) ? iattr->ia_gid : igid;
uid = (mask & ATTR_UID) ? iattr->ia_uid : iuid;

/*
* CAP_CHOWN overrides the following restrictions:
*
* If _POSIX_CHOWN_RESTRICTED is defined, this capability
* shall override the restriction that a process cannot
* change the user ID of a file it owns and the restriction
* that the group ID supplied to the chown() function
* shall be equal to either the group ID or one of the
* supplementary group IDs of the calling process.
*/
if ((iuid != uid ||
(igid != gid && !in_group_p((gid_t)gid))) &&
!capable(CAP_CHOWN)) {
code = XFS_ERROR(EPERM);
goto error_return;
}
/*
* Do a quota reservation only if uid/gid is actually
* going to change.
Expand Down Expand Up @@ -276,36 +213,22 @@ xfs_setattr(
code = XFS_ERROR(EINVAL);
goto error_return;
}

/*
* Make sure that the dquots are attached to the inode.
*/
if ((code = XFS_QM_DQATTACH(mp, ip, XFS_QMOPT_ILOCKED)))
code = XFS_QM_DQATTACH(mp, ip, XFS_QMOPT_ILOCKED);
if (code)
goto error_return;
}

/*
* Change file access or modified times.
*/
if (mask & (ATTR_ATIME|ATTR_MTIME)) {
if (!file_owner) {
if ((mask & (ATTR_MTIME_SET|ATTR_ATIME_SET)) &&
!capable(CAP_FOWNER)) {
code = XFS_ERROR(EPERM);
goto error_return;
}
}
}

/*
* Now we can make the changes. Before we join the inode
* to the transaction, if ATTR_SIZE is set then take care of
* the part of the truncation that must be done without the
* inode lock. This needs to be done before joining the inode
* to the transaction, because the inode cannot be unlocked
* once it is a part of the transaction.
*/
if (mask & ATTR_SIZE) {
code = 0;
/*
* Now we can make the changes. Before we join the inode
* to the transaction, if ATTR_SIZE is set then take care of
* the part of the truncation that must be done without the
* inode lock. This needs to be done before joining the inode
* to the transaction, because the inode cannot be unlocked
* once it is a part of the transaction.
*/
if (iattr->ia_size > ip->i_size) {
/*
* Do the first part of growing a file: zero any data
Expand Down Expand Up @@ -360,17 +283,10 @@ xfs_setattr(
}
commit_flags = XFS_TRANS_RELEASE_LOG_RES;
xfs_ilock(ip, XFS_ILOCK_EXCL);
}

if (tp) {
xfs_trans_ijoin(tp, ip, lock_flags);
xfs_trans_ihold(tp, ip);
}

/*
* Truncate file. Must have write permission and not be a directory.
*/
if (mask & ATTR_SIZE) {
/*
* Only change the c/mtime if we are changing the size
* or we are explicitly asked to change it. This handles
Expand Down Expand Up @@ -410,20 +326,9 @@ xfs_setattr(
*/
xfs_iflags_set(ip, XFS_ITRUNCATED);
}
}

/*
* Change file access modes.
*/
if (mask & ATTR_MODE) {
ip->i_d.di_mode &= S_IFMT;
ip->i_d.di_mode |= iattr->ia_mode & ~S_IFMT;

inode->i_mode &= S_IFMT;
inode->i_mode |= iattr->ia_mode & ~S_IFMT;

xfs_trans_log_inode (tp, ip, XFS_ILOG_CORE);
timeflags |= XFS_ICHGTIME_CHG;
} else if (tp) {
xfs_trans_ijoin(tp, ip, lock_flags);
xfs_trans_ihold(tp, ip);
}

/*
Expand Down Expand Up @@ -471,6 +376,24 @@ xfs_setattr(
timeflags |= XFS_ICHGTIME_CHG;
}

/*
* Change file access modes.
*/
if (mask & ATTR_MODE) {
umode_t mode = iattr->ia_mode;

if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
mode &= ~S_ISGID;

ip->i_d.di_mode &= S_IFMT;
ip->i_d.di_mode |= mode & ~S_IFMT;

inode->i_mode &= S_IFMT;
inode->i_mode |= mode & ~S_IFMT;

xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
timeflags |= XFS_ICHGTIME_CHG;
}

/*
* Change file access or modified times.
Expand Down

0 comments on commit 52424de

Please sign in to comment.