diff options
author | Darrick J. Wong <djwong@kernel.org> | 2022-05-23 08:43:46 +1000 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2022-05-23 08:43:46 +1000 |
commit | 4183e4f27f402d712bccab30588a6fe7575963c0 (patch) | |
tree | 0512397bff6c28e5371edcea24baef0051b77492 /fs/xfs/xfs_attr_item.h | |
parent | 22a68ba724232ba675166c307ddef3749ae4c37c (diff) | |
download | lwn-4183e4f27f402d712bccab30588a6fe7575963c0.tar.gz lwn-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/xfs_attr_item.h')
-rw-r--r-- | fs/xfs/xfs_attr_item.h | 13 |
1 files changed, 9 insertions, 4 deletions
diff --git a/fs/xfs/xfs_attr_item.h b/fs/xfs/xfs_attr_item.h index a40e702e0215..3280a7930287 100644 --- a/fs/xfs/xfs_attr_item.h +++ b/fs/xfs/xfs_attr_item.h @@ -11,6 +11,14 @@ struct xfs_mount; struct kmem_zone; +struct xfs_attri_log_nameval { + struct xfs_log_iovec name; + struct xfs_log_iovec value; + refcount_t refcount; + + /* name and value follow the end of this struct */ +}; + /* * This is the "attr intention" log item. It is used to log the fact that some * extended attribute operations need to be processed. An operation is @@ -26,10 +34,7 @@ struct kmem_zone; struct xfs_attri_log_item { struct xfs_log_item attri_item; atomic_t attri_refcount; - int attri_name_len; - int attri_value_len; - void *attri_name; - void *attri_value; + struct xfs_attri_log_nameval *attri_nameval; struct xfs_attri_log_format attri_format; }; |