linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCHSET 0/3] xfs: fix permission drop and flushing in fallocate
@ 2022-01-26  2:18 Darrick J. Wong
  2022-01-26  2:18 ` [PATCH 1/3] xfs: use vfs helper to update file attributes after fallocate Darrick J. Wong
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Darrick J. Wong @ 2022-01-26  2:18 UTC (permalink / raw)
  To: djwong; +Cc: linux-xfs, linux-fsdevel

Hi all,

While auditing the file permission dropping for fallocate, I reached the
conclusion that fallocate can modify file contents, and therefore should
be treated as a file write.  As such, it needs to update the file
modification and file (metadata) change timestamps, and it needs to drop
file privileges such as setuid and capabilities, just like a regular
write.  Moreover, if the inode is configured for synchronous writes,
then all the fallocate changes really ought to be persisted to disk
before fallocate returns to userspace.

Unfortunately, the XFS fallocate implementation doesn't do this
correctly.  setgid without group-exec is a mandatory locking mark and is
left alone by write(), which means that we shouldn't drop it
unconditionally.  Furthermore, file capabilities are another vector for
setuid to be set on a program file, and XFS ignores these.

I also noticed that fallocate doesn't flush the log to disk after
fallocate when the fs is mounted with -o sync or if the DIFLAG_SYNC flag
is set on the inode.

Therefore, refactor the XFS fallocate implementation to use the VFS
helper file_modified to update file metadata instead of open-coding it
incorrectly.  Refactor it further to use xfs_file_sync_writes to decide
if we need to flush the log; and then fix the log flushing so that it
flushes after we've made /all/ the changes.

If you're going to start using this mess, you probably ought to just
pull from my git trees, which are linked below.

This is an extraordinary way to destroy everything.  Enjoy!
Comments and questions are, as always, welcome.

--D

kernel git tree:
https://git.kernel.org/cgit/linux/kernel/git/djwong/xfs-linux.git/log/?h=falloc-fix-perm-updates-5.17
---
 fs/xfs/xfs_file.c |   72 ++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 52 insertions(+), 20 deletions(-)


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/3] xfs: use vfs helper to update file attributes after fallocate
  2022-01-26  2:18 [PATCHSET 0/3] xfs: fix permission drop and flushing in fallocate Darrick J. Wong
@ 2022-01-26  2:18 ` Darrick J. Wong
  2022-01-28  9:32   ` Chandan Babu R
  2022-01-26  2:18 ` [PATCH 2/3] xfs: flush log after fallocate for sync mounts and sync inodes Darrick J. Wong
  2022-01-26  2:19 ` [PATCH 3/3] xfs: ensure log flush at the end of a synchronous fallocate call Darrick J. Wong
  2 siblings, 1 reply; 9+ messages in thread
From: Darrick J. Wong @ 2022-01-26  2:18 UTC (permalink / raw)
  To: djwong; +Cc: linux-xfs, linux-fsdevel

From: Darrick J. Wong <djwong@kernel.org>

In XFS, we always update the inode change and modification time when any
preallocation operation succeeds.  Furthermore, as various fallocate
modes can change the file contents (extending EOF, punching holes,
zeroing things, shifting extents), we should drop file privileges like
suid just like we do for a regular write().  There's already a VFS
helper that figures all this out for us, so use that.

The net effect of this is that we no longer drop suid/sgid if the caller
is root, but we also now drop file capabilities.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
 fs/xfs/xfs_file.c |   23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)


diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 22ad207bedf4..eee5fb20cf8d 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -1057,13 +1057,28 @@ xfs_file_fallocate(
 		}
 	}
 
-	if (file->f_flags & O_DSYNC)
-		flags |= XFS_PREALLOC_SYNC;
-
-	error = xfs_update_prealloc_flags(ip, flags);
+	/* Update [cm]time and drop file privileges like a regular write. */
+	error = file_modified(file);
 	if (error)
 		goto out_unlock;
 
+	/*
+	 * If we need to change the PREALLOC flag, do so.  We already updated
+	 * the timestamps and cleared the suid flags, so we don't need to do
+	 * that again.  This must be committed before the size change so that
+	 * we don't trim post-EOF preallocations.
+	 */
+	if (flags) {
+		flags |= XFS_PREALLOC_INVISIBLE;
+
+		if (file->f_flags & O_DSYNC)
+			flags |= XFS_PREALLOC_SYNC;
+
+		error = xfs_update_prealloc_flags(ip, flags);
+		if (error)
+			goto out_unlock;
+	}
+
 	/* Change file size if needed */
 	if (new_size) {
 		struct iattr iattr;


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/3] xfs: flush log after fallocate for sync mounts and sync inodes
  2022-01-26  2:18 [PATCHSET 0/3] xfs: fix permission drop and flushing in fallocate Darrick J. Wong
  2022-01-26  2:18 ` [PATCH 1/3] xfs: use vfs helper to update file attributes after fallocate Darrick J. Wong
@ 2022-01-26  2:18 ` Darrick J. Wong
  2022-01-26  2:19 ` [PATCH 3/3] xfs: ensure log flush at the end of a synchronous fallocate call Darrick J. Wong
  2 siblings, 0 replies; 9+ messages in thread
From: Darrick J. Wong @ 2022-01-26  2:18 UTC (permalink / raw)
  To: djwong; +Cc: linux-xfs, linux-fsdevel

From: Darrick J. Wong <djwong@kernel.org>

Since we've started treating fallocate more like a file write, we should
flush the log to disk if the user has asked for synchronous writes
either by setting it via fcntl flags, or inode flags, or with the sync
mount option.  We've already got a helper for this, so use it.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
 fs/xfs/xfs_file.c |   32 ++++++++++++++++----------------
 1 file changed, 16 insertions(+), 16 deletions(-)


diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index eee5fb20cf8d..fb82a61696f0 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -895,6 +895,21 @@ xfs_break_layouts(
 	return error;
 }
 
+/* Does this file, inode, or mount want synchronous writes? */
+static inline bool xfs_file_sync_writes(struct file *filp)
+{
+	struct xfs_inode	*ip = XFS_I(file_inode(filp));
+
+	if (xfs_has_wsync(ip->i_mount))
+		return true;
+	if (filp->f_flags & (__O_SYNC | O_DSYNC))
+		return true;
+	if (IS_SYNC(file_inode(filp)))
+		return true;
+
+	return false;
+}
+
 #define	XFS_FALLOC_FL_SUPPORTED						\
 		(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE |		\
 		 FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE |	\
@@ -1071,7 +1086,7 @@ xfs_file_fallocate(
 	if (flags) {
 		flags |= XFS_PREALLOC_INVISIBLE;
 
-		if (file->f_flags & O_DSYNC)
+		if (xfs_file_sync_writes(file))
 			flags |= XFS_PREALLOC_SYNC;
 
 		error = xfs_update_prealloc_flags(ip, flags);
@@ -1130,21 +1145,6 @@ xfs_file_fadvise(
 	return ret;
 }
 
-/* Does this file, inode, or mount want synchronous writes? */
-static inline bool xfs_file_sync_writes(struct file *filp)
-{
-	struct xfs_inode	*ip = XFS_I(file_inode(filp));
-
-	if (xfs_has_wsync(ip->i_mount))
-		return true;
-	if (filp->f_flags & (__O_SYNC | O_DSYNC))
-		return true;
-	if (IS_SYNC(file_inode(filp)))
-		return true;
-
-	return false;
-}
-
 STATIC loff_t
 xfs_file_remap_range(
 	struct file		*file_in,


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/3] xfs: ensure log flush at the end of a synchronous fallocate call
  2022-01-26  2:18 [PATCHSET 0/3] xfs: fix permission drop and flushing in fallocate Darrick J. Wong
  2022-01-26  2:18 ` [PATCH 1/3] xfs: use vfs helper to update file attributes after fallocate Darrick J. Wong
  2022-01-26  2:18 ` [PATCH 2/3] xfs: flush log after fallocate for sync mounts and sync inodes Darrick J. Wong
@ 2022-01-26  2:19 ` Darrick J. Wong
  2 siblings, 0 replies; 9+ messages in thread
From: Darrick J. Wong @ 2022-01-26  2:19 UTC (permalink / raw)
  To: djwong; +Cc: linux-xfs, linux-fsdevel

From: Darrick J. Wong <djwong@kernel.org>

If the caller wanted us to persist the preallocation to disk before
returning to userspace, make sure we force the log to disk after making
all metadata updates.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
 fs/xfs/xfs_file.c |   23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)


diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index fb82a61696f0..8f2372b96fc4 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -929,6 +929,7 @@ xfs_file_fallocate(
 	uint			iolock = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL;
 	loff_t			new_size = 0;
 	bool			do_file_insert = false;
+	bool			flush_log;
 
 	if (!S_ISREG(inode->i_mode))
 		return -EINVAL;
@@ -1081,12 +1082,14 @@ xfs_file_fallocate(
 	 * If we need to change the PREALLOC flag, do so.  We already updated
 	 * the timestamps and cleared the suid flags, so we don't need to do
 	 * that again.  This must be committed before the size change so that
-	 * we don't trim post-EOF preallocations.
+	 * we don't trim post-EOF preallocations.  If this is the last
+	 * transaction we're going to make, make the update synchronous too.
 	 */
+	flush_log = xfs_file_sync_writes(file);
 	if (flags) {
 		flags |= XFS_PREALLOC_INVISIBLE;
 
-		if (xfs_file_sync_writes(file))
+		if (flush_log && !(do_file_insert || new_size))
 			flags |= XFS_PREALLOC_SYNC;
 
 		error = xfs_update_prealloc_flags(ip, flags);
@@ -1112,8 +1115,22 @@ xfs_file_fallocate(
 	 * leave shifted extents past EOF and hence losing access to
 	 * the data that is contained within them.
 	 */
-	if (do_file_insert)
+	if (do_file_insert) {
 		error = xfs_insert_file_space(ip, offset, len);
+		if (error)
+			goto out_unlock;
+	}
+
+	/*
+	 * If the caller wants us to flush the log and either we've made
+	 * changes since updating the PREALLOC flag or we didn't need to
+	 * update the PREALLOC flag, then flush the log now.
+	 */
+	if (flush_log && (do_file_insert || new_size || flags == 0)) {
+		error = xfs_log_force_inode(ip);
+		if (error)
+			goto out_unlock;
+	}
 
 out_unlock:
 	xfs_iunlock(ip, iolock);


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/3] xfs: use vfs helper to update file attributes after fallocate
  2022-01-26  2:18 ` [PATCH 1/3] xfs: use vfs helper to update file attributes after fallocate Darrick J. Wong
@ 2022-01-28  9:32   ` Chandan Babu R
  2022-01-28 22:23     ` Darrick J. Wong
  0 siblings, 1 reply; 9+ messages in thread
From: Chandan Babu R @ 2022-01-28  9:32 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, linux-fsdevel

On 26 Jan 2022 at 07:48, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
>
> In XFS, we always update the inode change and modification time when any
> preallocation operation succeeds.  Furthermore, as various fallocate
> modes can change the file contents (extending EOF, punching holes,
> zeroing things, shifting extents), we should drop file privileges like
> suid just like we do for a regular write().  There's already a VFS
> helper that figures all this out for us, so use that.
>
> The net effect of this is that we no longer drop suid/sgid if the caller
> is root, but we also now drop file capabilities.
>
> Signed-off-by: Darrick J. Wong <djwong@kernel.org>
> ---
>  fs/xfs/xfs_file.c |   23 +++++++++++++++++++----
>  1 file changed, 19 insertions(+), 4 deletions(-)
>
>
> diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
> index 22ad207bedf4..eee5fb20cf8d 100644
> --- a/fs/xfs/xfs_file.c
> +++ b/fs/xfs/xfs_file.c
> @@ -1057,13 +1057,28 @@ xfs_file_fallocate(
>  		}
>  	}
>  
> -	if (file->f_flags & O_DSYNC)
> -		flags |= XFS_PREALLOC_SYNC;
> -

Without the above change, if fallocate() is invoked with FALLOC_FL_PUNCH_HOLE,
FALLOC_FL_COLLAPSE_RANGE or FALLOC_FL_INSERT_RANGE, we used to update inode's
timestamp, remove setuid/setgid bits and then perform a synchronous
transaction commit if O_DSYNC flag is set.

However, with this patch applied, the transaction (inside
xfs_vn_update_time()) that updates file's inode contents (i.e. timestamps and
setuid/setgid bits) is not synchronous and hence the O_DSYNC flag is not
honored if the fallocate operation is one of FALLOC_FL_PUNCH_HOLE,
FALLOC_FL_COLLAPSE_RANGE or FALLOC_FL_INSERT_RANGE.

> -	error = xfs_update_prealloc_flags(ip, flags);
> +	/* Update [cm]time and drop file privileges like a regular write. */
> +	error = file_modified(file);
>  	if (error)
>  		goto out_unlock;
>  
> +	/*
> +	 * If we need to change the PREALLOC flag, do so.  We already updated
> +	 * the timestamps and cleared the suid flags, so we don't need to do
> +	 * that again.  This must be committed before the size change so that
> +	 * we don't trim post-EOF preallocations.
> +	 */
> +	if (flags) {
> +		flags |= XFS_PREALLOC_INVISIBLE;
> +
> +		if (file->f_flags & O_DSYNC)
> +			flags |= XFS_PREALLOC_SYNC;
> +
> +		error = xfs_update_prealloc_flags(ip, flags);
> +		if (error)
> +			goto out_unlock;
> +	}
> +
>  	/* Change file size if needed */
>  	if (new_size) {
>  		struct iattr iattr;

-- 
chandan

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/3] xfs: use vfs helper to update file attributes after fallocate
  2022-01-28  9:32   ` Chandan Babu R
@ 2022-01-28 22:23     ` Darrick J. Wong
  2022-01-29  7:43       ` Chandan Babu R
  0 siblings, 1 reply; 9+ messages in thread
From: Darrick J. Wong @ 2022-01-28 22:23 UTC (permalink / raw)
  To: Chandan Babu R; +Cc: linux-xfs, linux-fsdevel

On Fri, Jan 28, 2022 at 03:02:40PM +0530, Chandan Babu R wrote:
> On 26 Jan 2022 at 07:48, Darrick J. Wong wrote:
> > From: Darrick J. Wong <djwong@kernel.org>
> >
> > In XFS, we always update the inode change and modification time when any
> > preallocation operation succeeds.  Furthermore, as various fallocate
> > modes can change the file contents (extending EOF, punching holes,
> > zeroing things, shifting extents), we should drop file privileges like
> > suid just like we do for a regular write().  There's already a VFS
> > helper that figures all this out for us, so use that.
> >
> > The net effect of this is that we no longer drop suid/sgid if the caller
> > is root, but we also now drop file capabilities.
> >
> > Signed-off-by: Darrick J. Wong <djwong@kernel.org>
> > ---
> >  fs/xfs/xfs_file.c |   23 +++++++++++++++++++----
> >  1 file changed, 19 insertions(+), 4 deletions(-)
> >
> >
> > diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
> > index 22ad207bedf4..eee5fb20cf8d 100644
> > --- a/fs/xfs/xfs_file.c
> > +++ b/fs/xfs/xfs_file.c
> > @@ -1057,13 +1057,28 @@ xfs_file_fallocate(
> >  		}
> >  	}
> >  
> > -	if (file->f_flags & O_DSYNC)
> > -		flags |= XFS_PREALLOC_SYNC;
> > -
> 
> Without the above change, if fallocate() is invoked with FALLOC_FL_PUNCH_HOLE,
> FALLOC_FL_COLLAPSE_RANGE or FALLOC_FL_INSERT_RANGE, we used to update inode's
> timestamp, remove setuid/setgid bits and then perform a synchronous
> transaction commit if O_DSYNC flag is set.
> 
> However, with this patch applied, the transaction (inside
> xfs_vn_update_time()) that updates file's inode contents (i.e. timestamps and
> setuid/setgid bits) is not synchronous and hence the O_DSYNC flag is not
> honored if the fallocate operation is one of FALLOC_FL_PUNCH_HOLE,
> FALLOC_FL_COLLAPSE_RANGE or FALLOC_FL_INSERT_RANGE.

Ah, right.  This bug is covered up by the changes in the last patch, but
it would break bisection, so I'll clean that up and resubmit.  Thanks
for the comments!

> > -	error = xfs_update_prealloc_flags(ip, flags);
> > +	/* Update [cm]time and drop file privileges like a regular write. */
> > +	error = file_modified(file);
> >  	if (error)
> >  		goto out_unlock;
> >  
> > +	/*
> > +	 * If we need to change the PREALLOC flag, do so.  We already updated
> > +	 * the timestamps and cleared the suid flags, so we don't need to do
> > +	 * that again.  This must be committed before the size change so that
> > +	 * we don't trim post-EOF preallocations.
> > +	 */

So the code ends up looking like:

	if (file->f_flags & O_DSYNC)
		flags |= XFS_PREALLOC_SYNC;
	if (flags) {
		flags |= XFS_PREALLOC_INVISIBLE;

		error = xfs_update_prealloc_flags(ip, flags);
		if (error)
			goto out_unlock;
	}

--D

> > +	if (flags) {
> > +		flags |= XFS_PREALLOC_INVISIBLE;
> > +
> > +		if (file->f_flags & O_DSYNC)
> > +			flags |= XFS_PREALLOC_SYNC;
> > +
> > +		error = xfs_update_prealloc_flags(ip, flags);
> > +		if (error)
> > +			goto out_unlock;
> > +	}
> > +
> >  	/* Change file size if needed */
> >  	if (new_size) {
> >  		struct iattr iattr;
> 
> -- 
> chandan

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/3] xfs: use vfs helper to update file attributes after fallocate
  2022-01-28 22:23     ` Darrick J. Wong
@ 2022-01-29  7:43       ` Chandan Babu R
  0 siblings, 0 replies; 9+ messages in thread
From: Chandan Babu R @ 2022-01-29  7:43 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, linux-fsdevel

On 29 Jan 2022 at 03:53, Darrick J. Wong wrote:
> On Fri, Jan 28, 2022 at 03:02:40PM +0530, Chandan Babu R wrote:
>> On 26 Jan 2022 at 07:48, Darrick J. Wong wrote:
>> > From: Darrick J. Wong <djwong@kernel.org>
>> >
>> > In XFS, we always update the inode change and modification time when any
>> > preallocation operation succeeds.  Furthermore, as various fallocate
>> > modes can change the file contents (extending EOF, punching holes,
>> > zeroing things, shifting extents), we should drop file privileges like
>> > suid just like we do for a regular write().  There's already a VFS
>> > helper that figures all this out for us, so use that.
>> >
>> > The net effect of this is that we no longer drop suid/sgid if the caller
>> > is root, but we also now drop file capabilities.
>> >
>> > Signed-off-by: Darrick J. Wong <djwong@kernel.org>
>> > ---
>> >  fs/xfs/xfs_file.c |   23 +++++++++++++++++++----
>> >  1 file changed, 19 insertions(+), 4 deletions(-)
>> >
>> >
>> > diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
>> > index 22ad207bedf4..eee5fb20cf8d 100644
>> > --- a/fs/xfs/xfs_file.c
>> > +++ b/fs/xfs/xfs_file.c
>> > @@ -1057,13 +1057,28 @@ xfs_file_fallocate(
>> >  		}
>> >  	}
>> >  
>> > -	if (file->f_flags & O_DSYNC)
>> > -		flags |= XFS_PREALLOC_SYNC;
>> > -
>> 
>> Without the above change, if fallocate() is invoked with FALLOC_FL_PUNCH_HOLE,
>> FALLOC_FL_COLLAPSE_RANGE or FALLOC_FL_INSERT_RANGE, we used to update inode's
>> timestamp, remove setuid/setgid bits and then perform a synchronous
>> transaction commit if O_DSYNC flag is set.
>> 
>> However, with this patch applied, the transaction (inside
>> xfs_vn_update_time()) that updates file's inode contents (i.e. timestamps and
>> setuid/setgid bits) is not synchronous and hence the O_DSYNC flag is not
>> honored if the fallocate operation is one of FALLOC_FL_PUNCH_HOLE,
>> FALLOC_FL_COLLAPSE_RANGE or FALLOC_FL_INSERT_RANGE.
>
> Ah, right.  This bug is covered up by the changes in the last patch, but
> it would break bisection, so I'll clean that up and resubmit.  Thanks
> for the comments!
>
>> > -	error = xfs_update_prealloc_flags(ip, flags);
>> > +	/* Update [cm]time and drop file privileges like a regular write. */
>> > +	error = file_modified(file);
>> >  	if (error)
>> >  		goto out_unlock;
>> >  
>> > +	/*
>> > +	 * If we need to change the PREALLOC flag, do so.  We already updated
>> > +	 * the timestamps and cleared the suid flags, so we don't need to do
>> > +	 * that again.  This must be committed before the size change so that
>> > +	 * we don't trim post-EOF preallocations.
>> > +	 */
>
> So the code ends up looking like:
>
> 	if (file->f_flags & O_DSYNC)
> 		flags |= XFS_PREALLOC_SYNC;
> 	if (flags) {
> 		flags |= XFS_PREALLOC_INVISIBLE;
>
> 		error = xfs_update_prealloc_flags(ip, flags);
> 		if (error)
> 			goto out_unlock;
> 	}
>

The above change looks good to me.

>> > +	if (flags) {
>> > +		flags |= XFS_PREALLOC_INVISIBLE;
>> > +
>> > +		if (file->f_flags & O_DSYNC)
>> > +			flags |= XFS_PREALLOC_SYNC;
>> > +
>> > +		error = xfs_update_prealloc_flags(ip, flags);
>> > +		if (error)
>> > +			goto out_unlock;
>> > +	}
>> > +
>> >  	/* Change file size if needed */
>> >  	if (new_size) {
>> >  		struct iattr iattr;

-- 
chandan

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/3] xfs: use vfs helper to update file attributes after fallocate
  2022-01-30  4:59 ` [PATCH 1/3] xfs: use vfs helper to update file attributes after fallocate Darrick J. Wong
@ 2022-01-30 22:30   ` Dave Chinner
  0 siblings, 0 replies; 9+ messages in thread
From: Dave Chinner @ 2022-01-30 22:30 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, chandan.babu, linux-fsdevel

On Sat, Jan 29, 2022 at 08:59:29PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
> 
> In XFS, we always update the inode change and modification time when any
> preallocation operation succeeds.  Furthermore, as various fallocate
> modes can change the file contents (extending EOF, punching holes,
> zeroing things, shifting extents), we should drop file privileges like
> suid just like we do for a regular write().  There's already a VFS
> helper that figures all this out for us, so use that.
> 
> The net effect of this is that we no longer drop suid/sgid if the caller
> is root, but we also now drop file capabilities.
> 
> Signed-off-by: Darrick J. Wong <djwong@kernel.org>
> ---
>  fs/xfs/xfs_file.c |   20 +++++++++++++++++---
>  1 file changed, 17 insertions(+), 3 deletions(-)
> 
> 
> diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
> index 22ad207bedf4..3b0d026396e5 100644
> --- a/fs/xfs/xfs_file.c
> +++ b/fs/xfs/xfs_file.c
> @@ -1057,12 +1057,26 @@ xfs_file_fallocate(
>  		}
>  	}
>  
> +	/* Update [cm]time and drop file privileges like a regular write. */
> +	error = file_modified(file);
> +	if (error)
> +		goto out_unlock;
> +
> +	/*
> +	 * If we need to change the PREALLOC flag or flush the log, do so.
> +	 * We already updated the timestamps and cleared the suid flags, so we
> +	 * don't need to do that again.  This must be committed before the size
> +	 * change so that we don't trim post-EOF preallocations.
> +	 */
>  	if (file->f_flags & O_DSYNC)
>  		flags |= XFS_PREALLOC_SYNC;
> +	if (flags) {
> +		flags |= XFS_PREALLOC_INVISIBLE;
> -	error = xfs_update_prealloc_flags(ip, flags);
> -	if (error)
> -		goto out_unlock;
> +		error = xfs_update_prealloc_flags(ip, flags);
> +		if (error)
> +			goto out_unlock;
> +	}

That's a change of behaviour in that if O_DSYNC is not used, we
won't call xfs_update_prealloc_flags() and so won't always log the
inode here, regardless of whether the timestamps are changed or not.

Regardless, the only other caller of xfs_update_prealloc_flags() is
xfs_fs_map_blocks(), and that clearly modifies the layout of the
file so it has the same issue w.r.t. stripping privileges via
xfs_update_prealloc_flags(). So it should really also
and not the open coded stripping done in
xfs_update_prealloc_flags().

As such, I think that the use of XFS_PREALLOC_INVISIBLE here is not
a very nice workaround to avoid repeating the work done by
file_modified(). All the code that does direct extent modification
should perform the same actions for the same reasons. And if you
xfs_fs_map_blocks() to use xfs_log_force_inode() like patch 3 in
this series does for fallocate(), then XFS_PREALLOC_SYNC and that
code in xfs_update_prealloc_flags() can go away as well....

Cheers,

Dave.
-- 
Dave Chinner
david@fromorbit.com

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/3] xfs: use vfs helper to update file attributes after fallocate
  2022-01-30  4:59 [PATCHSET v2 0/3] xfs: fix permission drop and flushing in fallocate Darrick J. Wong
@ 2022-01-30  4:59 ` Darrick J. Wong
  2022-01-30 22:30   ` Dave Chinner
  0 siblings, 1 reply; 9+ messages in thread
From: Darrick J. Wong @ 2022-01-30  4:59 UTC (permalink / raw)
  To: djwong; +Cc: linux-xfs, chandan.babu, linux-fsdevel

From: Darrick J. Wong <djwong@kernel.org>

In XFS, we always update the inode change and modification time when any
preallocation operation succeeds.  Furthermore, as various fallocate
modes can change the file contents (extending EOF, punching holes,
zeroing things, shifting extents), we should drop file privileges like
suid just like we do for a regular write().  There's already a VFS
helper that figures all this out for us, so use that.

The net effect of this is that we no longer drop suid/sgid if the caller
is root, but we also now drop file capabilities.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
 fs/xfs/xfs_file.c |   20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)


diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 22ad207bedf4..3b0d026396e5 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -1057,12 +1057,26 @@ xfs_file_fallocate(
 		}
 	}
 
+	/* Update [cm]time and drop file privileges like a regular write. */
+	error = file_modified(file);
+	if (error)
+		goto out_unlock;
+
+	/*
+	 * If we need to change the PREALLOC flag or flush the log, do so.
+	 * We already updated the timestamps and cleared the suid flags, so we
+	 * don't need to do that again.  This must be committed before the size
+	 * change so that we don't trim post-EOF preallocations.
+	 */
 	if (file->f_flags & O_DSYNC)
 		flags |= XFS_PREALLOC_SYNC;
+	if (flags) {
+		flags |= XFS_PREALLOC_INVISIBLE;
 
-	error = xfs_update_prealloc_flags(ip, flags);
-	if (error)
-		goto out_unlock;
+		error = xfs_update_prealloc_flags(ip, flags);
+		if (error)
+			goto out_unlock;
+	}
 
 	/* Change file size if needed */
 	if (new_size) {


^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2022-01-30 22:30 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-26  2:18 [PATCHSET 0/3] xfs: fix permission drop and flushing in fallocate Darrick J. Wong
2022-01-26  2:18 ` [PATCH 1/3] xfs: use vfs helper to update file attributes after fallocate Darrick J. Wong
2022-01-28  9:32   ` Chandan Babu R
2022-01-28 22:23     ` Darrick J. Wong
2022-01-29  7:43       ` Chandan Babu R
2022-01-26  2:18 ` [PATCH 2/3] xfs: flush log after fallocate for sync mounts and sync inodes Darrick J. Wong
2022-01-26  2:19 ` [PATCH 3/3] xfs: ensure log flush at the end of a synchronous fallocate call Darrick J. Wong
2022-01-30  4:59 [PATCHSET v2 0/3] xfs: fix permission drop and flushing in fallocate Darrick J. Wong
2022-01-30  4:59 ` [PATCH 1/3] xfs: use vfs helper to update file attributes after fallocate Darrick J. Wong
2022-01-30 22:30   ` Dave Chinner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).