mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-25 05:34:00 +08:00
Fixes for 5.17-rc3:
- Fix fallocate so that it drops all file privileges when files are modified instead of open-coding that incompletely. - Fix fallocate to flush the log if the caller wanted synchronous file updates. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEUzaAxoMeQq6m2jMV+H93GTRKtOsFAmH7/7wACgkQ+H93GTRK tOut/BAAl2aLNDdBjjp9rBbNdnZtXSQ3JKBo/6FrGX+7M2rr5/Ppskzfm2FE6HQj TS4CNAg1Gid/gbK956iOU+E3LvGR1lUA3yhtm0OZ7yffQ+1zGA2RUCTy39SZEUTI PTpzF6gH/oZAKrfv2r9yLEFJdPyBoo8BBBHBRshw5TiDqMG1pJ3toTySehLXHsRf Bf4pXGyOy0+q9zkIprUQg5l3cEEdoOW5mLwv/1soiLx+mz6Go/MHFaAO/U3m2KBq mwNUZcXoRSihyd7xKEqLQfYuy7abrtICsupoMGvCzFI1ox1ZzPN5/aNAI1LBXz8+ tK+gRaJg7stGVuI28zIEw4mmcLWG+h46fyuunhY6EIcoXZzpcXL9gxQzle6ypE8e ScRtRnjUd4CsDyRNzDez082K1T6M6pD3QXMWPn29/WnjKElbEKwqDRjri4HOqwyq A3buwhvuzK2ZS8f2k1/YLrNqZLCZwd9LRsz085GI7HUp7cardiTFERNzt4Nt935k T6lDFNKXVW9MZvSXGWNGmwHAQRvmkW+i7pyhE1LCsTwF0Q6YNwbhZAl9SJK5S5Zk TJEam4d6xY86Ppu7kXcYWtv8gJxMJyiGbywI8xZDz1VrkwNbfB0ZK/8A9KEMGc1r fuUxTZF12BY5Sm5YaxlmrDnkkvn3K9CHQ3DI7BiP+IldwDdhuOU= =dqTg -----END PGP SIGNATURE----- Merge tag 'xfs-5.17-fixes-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux Pull xfs fixes from Darrick Wong: "I was auditing operations in XFS that clear file privileges, and realized that XFS' fallocate implementation drops suid/sgid but doesn't clear file capabilities the same way that file writes and reflink do. There are VFS helpers that do it correctly, so refactor XFS to use them. I also noticed that we weren't flushing the log at the correct point in the fallocate operation, so that's fixed too. Summary: - Fix fallocate so that it drops all file privileges when files are modified instead of open-coding that incompletely. - Fix fallocate to flush the log if the caller wanted synchronous file updates" * tag 'xfs-5.17-fixes-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: xfs: ensure log flush at the end of a synchronous fallocate call xfs: move xfs_update_prealloc_flags() to xfs_pnfs.c xfs: set prealloc flag in xfs_alloc_file_space() xfs: fallocate() should call file_modified() xfs: remove XFS_PREALLOC_SYNC xfs: reject crazy array sizes being fed to XFS_IOC_GETBMAP*
This commit is contained in:
commit
fbc04bf01a
@ -850,9 +850,6 @@ xfs_alloc_file_space(
|
||||
rblocks = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate and setup the transaction.
|
||||
*/
|
||||
error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write,
|
||||
dblocks, rblocks, false, &tp);
|
||||
if (error)
|
||||
@ -869,9 +866,9 @@ xfs_alloc_file_space(
|
||||
if (error)
|
||||
goto error;
|
||||
|
||||
/*
|
||||
* Complete the transaction
|
||||
*/
|
||||
ip->i_diflags |= XFS_DIFLAG_PREALLOC;
|
||||
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
||||
|
||||
error = xfs_trans_commit(tp);
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
if (error)
|
||||
|
@ -66,40 +66,6 @@ xfs_is_falloc_aligned(
|
||||
return !((pos | len) & mask);
|
||||
}
|
||||
|
||||
int
|
||||
xfs_update_prealloc_flags(
|
||||
struct xfs_inode *ip,
|
||||
enum xfs_prealloc_flags flags)
|
||||
{
|
||||
struct xfs_trans *tp;
|
||||
int error;
|
||||
|
||||
error = xfs_trans_alloc(ip->i_mount, &M_RES(ip->i_mount)->tr_writeid,
|
||||
0, 0, 0, &tp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
|
||||
|
||||
if (!(flags & XFS_PREALLOC_INVISIBLE)) {
|
||||
VFS_I(ip)->i_mode &= ~S_ISUID;
|
||||
if (VFS_I(ip)->i_mode & S_IXGRP)
|
||||
VFS_I(ip)->i_mode &= ~S_ISGID;
|
||||
xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
|
||||
}
|
||||
|
||||
if (flags & XFS_PREALLOC_SET)
|
||||
ip->i_diflags |= XFS_DIFLAG_PREALLOC;
|
||||
if (flags & XFS_PREALLOC_CLEAR)
|
||||
ip->i_diflags &= ~XFS_DIFLAG_PREALLOC;
|
||||
|
||||
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
||||
if (flags & XFS_PREALLOC_SYNC)
|
||||
xfs_trans_set_sync(tp);
|
||||
return xfs_trans_commit(tp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fsync operations on directories are much simpler than on regular files,
|
||||
* as there is no file data to flush, and thus also no need for explicit
|
||||
@ -895,6 +861,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 | \
|
||||
@ -910,7 +891,6 @@ xfs_file_fallocate(
|
||||
struct inode *inode = file_inode(file);
|
||||
struct xfs_inode *ip = XFS_I(inode);
|
||||
long error;
|
||||
enum xfs_prealloc_flags flags = 0;
|
||||
uint iolock = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL;
|
||||
loff_t new_size = 0;
|
||||
bool do_file_insert = false;
|
||||
@ -955,6 +935,10 @@ xfs_file_fallocate(
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
error = file_modified(file);
|
||||
if (error)
|
||||
goto out_unlock;
|
||||
|
||||
if (mode & FALLOC_FL_PUNCH_HOLE) {
|
||||
error = xfs_free_file_space(ip, offset, len);
|
||||
if (error)
|
||||
@ -1004,8 +988,6 @@ xfs_file_fallocate(
|
||||
}
|
||||
do_file_insert = true;
|
||||
} else {
|
||||
flags |= XFS_PREALLOC_SET;
|
||||
|
||||
if (!(mode & FALLOC_FL_KEEP_SIZE) &&
|
||||
offset + len > i_size_read(inode)) {
|
||||
new_size = offset + len;
|
||||
@ -1057,13 +1039,6 @@ xfs_file_fallocate(
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
@ -1082,8 +1057,14 @@ 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 (xfs_file_sync_writes(file))
|
||||
error = xfs_log_force_inode(ip);
|
||||
|
||||
out_unlock:
|
||||
xfs_iunlock(ip, iolock);
|
||||
@ -1115,21 +1096,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,
|
||||
|
@ -462,15 +462,6 @@ xfs_itruncate_extents(
|
||||
}
|
||||
|
||||
/* from xfs_file.c */
|
||||
enum xfs_prealloc_flags {
|
||||
XFS_PREALLOC_SET = (1 << 1),
|
||||
XFS_PREALLOC_CLEAR = (1 << 2),
|
||||
XFS_PREALLOC_SYNC = (1 << 3),
|
||||
XFS_PREALLOC_INVISIBLE = (1 << 4),
|
||||
};
|
||||
|
||||
int xfs_update_prealloc_flags(struct xfs_inode *ip,
|
||||
enum xfs_prealloc_flags flags);
|
||||
int xfs_break_layouts(struct inode *inode, uint *iolock,
|
||||
enum layout_break_reason reason);
|
||||
|
||||
|
@ -1464,7 +1464,7 @@ xfs_ioc_getbmap(
|
||||
|
||||
if (bmx.bmv_count < 2)
|
||||
return -EINVAL;
|
||||
if (bmx.bmv_count > ULONG_MAX / recsize)
|
||||
if (bmx.bmv_count >= INT_MAX / recsize)
|
||||
return -ENOMEM;
|
||||
|
||||
buf = kvcalloc(bmx.bmv_count, sizeof(*buf), GFP_KERNEL);
|
||||
|
@ -70,6 +70,40 @@ xfs_fs_get_uuid(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We cannot use file based VFS helpers such as file_modified() to update
|
||||
* inode state as we modify the data/metadata in the inode here. Hence we have
|
||||
* to open code the timestamp updates and SUID/SGID stripping. We also need
|
||||
* to set the inode prealloc flag to ensure that the extents we allocate are not
|
||||
* removed if the inode is reclaimed from memory before xfs_fs_block_commit()
|
||||
* is from the client to indicate that data has been written and the file size
|
||||
* can be extended.
|
||||
*/
|
||||
static int
|
||||
xfs_fs_map_update_inode(
|
||||
struct xfs_inode *ip)
|
||||
{
|
||||
struct xfs_trans *tp;
|
||||
int error;
|
||||
|
||||
error = xfs_trans_alloc(ip->i_mount, &M_RES(ip->i_mount)->tr_writeid,
|
||||
0, 0, 0, &tp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
|
||||
|
||||
VFS_I(ip)->i_mode &= ~S_ISUID;
|
||||
if (VFS_I(ip)->i_mode & S_IXGRP)
|
||||
VFS_I(ip)->i_mode &= ~S_ISGID;
|
||||
xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
|
||||
ip->i_diflags |= XFS_DIFLAG_PREALLOC;
|
||||
|
||||
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
||||
return xfs_trans_commit(tp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a layout for the pNFS client.
|
||||
*/
|
||||
@ -164,10 +198,12 @@ xfs_fs_map_blocks(
|
||||
* that the blocks allocated and handed out to the client are
|
||||
* guaranteed to be present even after a server crash.
|
||||
*/
|
||||
error = xfs_update_prealloc_flags(ip,
|
||||
XFS_PREALLOC_SET | XFS_PREALLOC_SYNC);
|
||||
error = xfs_fs_map_update_inode(ip);
|
||||
if (!error)
|
||||
error = xfs_log_force_inode(ip);
|
||||
if (error)
|
||||
goto out_unlock;
|
||||
|
||||
} else {
|
||||
xfs_iunlock(ip, lock_flags);
|
||||
}
|
||||
@ -255,7 +291,7 @@ xfs_fs_commit_blocks(
|
||||
length = end - start;
|
||||
if (!length)
|
||||
continue;
|
||||
|
||||
|
||||
/*
|
||||
* Make sure reads through the pagecache see the new data.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user