xfs: kill suid/sgid through the truncate path.
XFS has failed to kill suid/sgid bits correctly when truncating files of non-zero size since commitc4ed4243
("xfs: split xfs_setattr") introduced in the 3.1 kernel. Fix it. Fix it. cc: stable kernel <stable@vger.kernel.org> Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Ben Myers <bpm@sgi.com> (cherry picked from commit56c19e89b3
)
This commit is contained in:
parent
08fb39051f
commit
2962f5a5dc
1 changed files with 32 additions and 15 deletions
|
@ -455,6 +455,28 @@ xfs_vn_getattr(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xfs_setattr_mode(
|
||||||
|
struct xfs_trans *tp,
|
||||||
|
struct xfs_inode *ip,
|
||||||
|
struct iattr *iattr)
|
||||||
|
{
|
||||||
|
struct inode *inode = VFS_I(ip);
|
||||||
|
umode_t mode = iattr->ia_mode;
|
||||||
|
|
||||||
|
ASSERT(tp);
|
||||||
|
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
xfs_setattr_nonsize(
|
xfs_setattr_nonsize(
|
||||||
struct xfs_inode *ip,
|
struct xfs_inode *ip,
|
||||||
|
@ -606,18 +628,8 @@ xfs_setattr_nonsize(
|
||||||
/*
|
/*
|
||||||
* Change file access modes.
|
* Change file access modes.
|
||||||
*/
|
*/
|
||||||
if (mask & ATTR_MODE) {
|
if (mask & ATTR_MODE)
|
||||||
umode_t mode = iattr->ia_mode;
|
xfs_setattr_mode(tp, ip, iattr);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Change file access or modified times.
|
* Change file access or modified times.
|
||||||
|
@ -714,9 +726,8 @@ xfs_setattr_size(
|
||||||
return XFS_ERROR(error);
|
return XFS_ERROR(error);
|
||||||
|
|
||||||
ASSERT(S_ISREG(ip->i_d.di_mode));
|
ASSERT(S_ISREG(ip->i_d.di_mode));
|
||||||
ASSERT((mask & (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET|
|
ASSERT((mask & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET|
|
||||||
ATTR_MTIME_SET|ATTR_KILL_SUID|ATTR_KILL_SGID|
|
ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0);
|
||||||
ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0);
|
|
||||||
|
|
||||||
if (!(flags & XFS_ATTR_NOLOCK)) {
|
if (!(flags & XFS_ATTR_NOLOCK)) {
|
||||||
lock_flags |= XFS_IOLOCK_EXCL;
|
lock_flags |= XFS_IOLOCK_EXCL;
|
||||||
|
@ -860,6 +871,12 @@ xfs_setattr_size(
|
||||||
xfs_inode_clear_eofblocks_tag(ip);
|
xfs_inode_clear_eofblocks_tag(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Change file access modes.
|
||||||
|
*/
|
||||||
|
if (mask & ATTR_MODE)
|
||||||
|
xfs_setattr_mode(tp, ip, iattr);
|
||||||
|
|
||||||
if (mask & ATTR_CTIME) {
|
if (mask & ATTR_CTIME) {
|
||||||
inode->i_ctime = iattr->ia_ctime;
|
inode->i_ctime = iattr->ia_ctime;
|
||||||
ip->i_d.di_ctime.t_sec = iattr->ia_ctime.tv_sec;
|
ip->i_d.di_ctime.t_sec = iattr->ia_ctime.tv_sec;
|
||||||
|
|
Loading…
Add table
Reference in a new issue