aboutsummaryrefslogtreecommitdiff
path: root/fs/xfs/libxfs/xfs_attr.h
diff options
context:
space:
mode:
authorGravatar Darrick J. Wong <djwong@kernel.org> 2022-05-23 08:43:46 +1000
committerGravatar Dave Chinner <david@fromorbit.com> 2022-05-23 08:43:46 +1000
commit4183e4f27f402d712bccab30588a6fe7575963c0 (patch)
tree0512397bff6c28e5371edcea24baef0051b77492 /fs/xfs/libxfs/xfs_attr.h
parentxfs: do not use logged xattr updates on V4 filesystems (diff)
downloadlinux-4183e4f27f402d712bccab30588a6fe7575963c0.tar.gz
linux-4183e4f27f402d712bccab30588a6fe7575963c0.tar.bz2
linux-4183e4f27f402d712bccab30588a6fe7575963c0.zip
xfs: share xattr name and value buffers when logging xattr updates
While running xfs/297 and generic/642, I noticed a crash in xfs_attri_item_relog when it tries to copy the attr name to the new xattri log item. I think what happened here was that we called ->iop_commit on the old attri item (which nulls out the pointers) as part of a log force at the same time that a chained attr operation was ongoing. The system was busy enough that at some later point, the defer ops operation decided it was necessary to relog the attri log item, but as we've detached the name buffer from the old attri log item, we can't copy it to the new one, and kaboom. I think there's a broader refcounting problem with LARP mode -- the setxattr code can return to userspace before the CIL actually formats and commits the log item, which results in a UAF bug. Therefore, the xattr log item needs to be able to retain a reference to the name and value buffers until the log items have completely cleared the log. Furthermore, each time we create an intent log item, we allocate new memory and (re)copy the contents; sharing here would be very useful. Solve the UAF and the unnecessary memory allocations by having the log code create a single refcounted buffer to contain the name and value contents. This buffer can be passed from old to new during a relog operation, and the logging code can (optionally) attach it to the xfs_attr_item for reuse when LARP mode is enabled. This also fixes a problem where the xfs_attri_log_item objects weren't being freed back to the same cache where they came from. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs/libxfs/xfs_attr.h')
-rw-r--r--fs/xfs/libxfs/xfs_attr.h8
1 files changed, 8 insertions, 0 deletions
diff --git a/fs/xfs/libxfs/xfs_attr.h b/fs/xfs/libxfs/xfs_attr.h
index 3cd9cbb68b0f..e329da3e7afa 100644
--- a/fs/xfs/libxfs/xfs_attr.h
+++ b/fs/xfs/libxfs/xfs_attr.h
@@ -502,6 +502,8 @@ enum xfs_delattr_state {
{ XFS_DAS_NODE_REMOVE_ATTR, "XFS_DAS_NODE_REMOVE_ATTR" }, \
{ XFS_DAS_DONE, "XFS_DAS_DONE" }
+struct xfs_attri_log_nameval;
+
/*
* Context used for keeping track of delayed attribute operations
*/
@@ -518,6 +520,12 @@ struct xfs_attr_intent {
struct xfs_da_args *xattri_da_args;
/*
+ * Shared buffer containing the attr name and value so that the logging
+ * code can share large memory buffers between log items.
+ */
+ struct xfs_attri_log_nameval *xattri_nameval;
+
+ /*
* Used by xfs_attr_set to hold a leaf buffer across a transaction roll
*/
struct xfs_buf *xattri_leaf_bp;