Commit 81428790 authored by Dave Chinner's avatar Dave Chinner Committed by Ben Hutchings

xfs: kill suid/sgid through the truncate path.

commit 2962f5a5 upstream.

XFS has failed to kill suid/sgid bits correctly when truncating
files of non-zero size since commit c4ed4243 ("xfs: split
xfs_setattr") introduced in the 3.1 kernel. Fix it.

Fix it.
Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
Signed-off-by: default avatarBen Myers <bpm@sgi.com>

(cherry picked from commit 56c19e89)
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
parent e597b7c3
...@@ -507,6 +507,28 @@ xfs_vn_getattr( ...@@ -507,6 +507,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,
...@@ -658,18 +680,8 @@ xfs_setattr_nonsize( ...@@ -658,18 +680,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.
...@@ -768,9 +780,8 @@ xfs_setattr_size( ...@@ -768,9 +780,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);
lock_flags = XFS_ILOCK_EXCL; lock_flags = XFS_ILOCK_EXCL;
if (!(flags & XFS_ATTR_NOLOCK)) if (!(flags & XFS_ATTR_NOLOCK))
...@@ -902,6 +913,12 @@ xfs_setattr_size( ...@@ -902,6 +913,12 @@ xfs_setattr_size(
xfs_iflags_set(ip, XFS_ITRUNCATED); xfs_iflags_set(ip, XFS_ITRUNCATED);
} }
/*
* 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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment