linux/fs/gfs2
Andreas Gruenbacher 9287c6452d gfs2: Fix occasional glock use-after-free
This patch has to do with the life cycle of glocks and buffers.  When
gfs2 metadata or journaled data is queued to be written, a gfs2_bufdata
object is assigned to track the buffer, and that is queued to various
lists, including the glock's gl_ail_list to indicate it's on the active
items list.  Once the page associated with the buffer has been written,
it is removed from the ail list, but its life isn't over until a revoke
has been successfully written.

So after the block is written, its bufdata object is moved from the
glock's gl_ail_list to a file-system-wide list of pending revokes,
sd_log_le_revoke.  At that point the glock still needs to track how many
revokes it contributed to that list (in gl_revokes) so that things like
glock go_sync can ensure all the metadata has been not only written, but
also revoked before the glock is granted to a different node.  This is
to guarantee journal replay doesn't replay the block once the glock has
been granted to another node.

Ross Lagerwall recently discovered a race in which an inode could be
evicted, and its glock freed after its ail list had been synced, but
while it still had unwritten revokes on the sd_log_le_revoke list.  The
evict decremented the glock reference count to zero, which allowed the
glock to be freed.  After the revoke was written, function
revoke_lo_after_commit tried to adjust the glock's gl_revokes counter
and clear its GLF_LFLUSH flag, at which time it referenced the freed
glock.

This patch fixes the problem by incrementing the glock reference count
in gfs2_add_revoke when the glock's first bufdata object is moved from
the glock to the global revokes list. Later, when the glock's last such
bufdata object is freed, the reference count is decremented. This
guarantees that whichever process finishes last (the revoke writing or
the evict) will properly free the glock, and neither will reference the
glock after it has been freed.

Reported-by: Ross Lagerwall <ross.lagerwall@citrix.com>
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
2019-05-07 23:39:14 +02:00
..
acl.c gfs2: using posix_acl_xattr_size instead of posix_acl_to_xattr 2018-07-24 20:02:11 +02:00
acl.h gfs2: Switch to generic xattr handlers 2016-05-12 22:28:05 -04:00
aops.c gfs2: Fix the gfs2_invalidatepage description 2018-12-11 17:50:35 +01:00
aops.h gfs2: iomap buffered write support 2018-07-02 16:27:17 +01:00
bmap.c gfs2: clean_journal improperly set sd_log_flush_head 2019-05-07 23:39:04 +02:00
bmap.h gfs2: clean_journal improperly set sd_log_flush_head 2019-05-07 23:39:04 +02:00
dentry.c gfs2: Lock holder cleanup 2016-06-27 09:47:09 -05:00
dir.c gfs2: Pass resource group to rgblk_free 2018-10-12 07:33:07 -05:00
dir.h
export.c gfs2: Get rid of gfs2_ilookup 2016-06-27 09:47:08 -05:00
file.c iomap: wire up the iopoll method 2019-02-24 08:20:17 -07:00
gfs2.h
glock.c gfs2: Fix occasional glock use-after-free 2019-05-07 23:39:14 +02:00
glock.h gfs: no need to check return value of debugfs_create functions 2019-01-23 12:30:34 +01:00
glops.c Revert "gfs2: read journal in large chunks to locate the head" 2019-02-14 09:52:51 -08:00
glops.h
incore.h gfs2: clean_journal improperly set sd_log_flush_head 2019-05-07 23:39:04 +02:00
inode.c gfs2: Get rid of potential double-freeing in gfs2_create_inode 2018-12-11 21:44:29 +01:00
inode.h gfs2: Fix an incorrect gfs2_assert() 2019-03-06 07:00:43 -07:00
Kconfig gfs2: Fix the crc32c dependency 2018-02-01 11:25:31 -07:00
lock_dlm.c gfs2: Use fs_* functions instead of pr_* function where we can 2018-10-05 11:16:54 -05:00
log.c gfs2: Fix occasional glock use-after-free 2019-05-07 23:39:14 +02:00
log.h gfs2: clean_journal improperly set sd_log_flush_head 2019-05-07 23:39:04 +02:00
lops.c gfs2: Fix occasional glock use-after-free 2019-05-07 23:39:14 +02:00
lops.h gfs2: clean_journal improperly set sd_log_flush_head 2019-05-07 23:39:04 +02:00
main.c gfs: no need to check return value of debugfs_create functions 2019-01-23 12:30:34 +01:00
Makefile License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
meta_io.c block: allow bio_for_each_segment_all() to iterate over multi-page bvec 2019-02-15 08:40:11 -07:00
meta_io.h GFS2: Refactor gfs2_remove_from_journal 2016-05-06 11:27:27 -05:00
ops_fstype.c Revert "gfs2: read journal in large chunks to locate the head" 2019-02-14 09:52:51 -08:00
quota.c gfs2: Fix some minor typos 2018-10-12 07:31:21 -05:00
quota.h gfs2: Fix fallocate chunk size 2018-03-08 09:26:20 -07:00
recovery.c gfs2: clean_journal improperly set sd_log_flush_head 2019-05-07 23:39:04 +02:00
recovery.h gfs2: clean_journal improperly set sd_log_flush_head 2019-05-07 23:39:04 +02:00
rgrp.c gfs2: Fix loop in gfs2_rbm_find (v2) 2019-05-07 22:33:44 +02:00
rgrp.h gfs2: Dump nrpages for inodes and their glocks 2018-12-12 12:33:23 +01:00
super.c gfs2: switch to ->free_inode() 2019-05-01 22:43:24 -04:00
super.h
sys.c GFS2: Fix recovery issues for spectators 2018-07-25 00:06:24 +02:00
sys.h
trace_gfs2.h gfs2: eliminate rs_inum and reduce the size of gfs2 inodes 2018-06-21 07:39:31 -05:00
trans.c gfs2: Remove vestigial bd_ops 2018-12-11 21:43:58 +01:00
trans.h gfs2: Eliminate redundant ip->i_rgd 2018-07-05 17:47:16 +02:00
util.c gfs2: slow the deluge of io error messages 2018-10-05 10:51:11 -05:00
util.h gfs2: Use fs_* functions instead of pr_* function where we can 2018-10-05 11:16:54 -05:00
xattr.c gfs2: Pass resource group to rgblk_free 2018-10-12 07:33:07 -05:00
xattr.h gfs2: Remove gfs2_xattr_acl_chmod 2015-12-06 21:25:17 -05:00