diff options
author | David Chinner <dgc@sgi.com> | 2006-09-27 21:06:03 -0400 |
---|---|---|
committer | Tim Shimmin <tes@sgi.com> | 2006-09-27 21:06:03 -0400 |
commit | f273ab848b7cbc0088b0ac7457b3769e6566074e (patch) | |
tree | 27f1b0ce7b056f77e7105284524cbdb658943ae5 /fs/xfs/xfs_iget.c | |
parent | 01106eae97b70399ce5a273a3cceb5246e8d9cc8 (diff) |
[XFS] Really fix use after free in xfs_iunpin.
The previous attempts to fix the linux inode use-after-free in xfs_iunpin
simply made the problem harder to hit. We actually need complete exclusion
between xfs_reclaim and xfs_iunpin, as well as ensuring that the i_flags
are consistent during both of these functions. Introduce a new spinlock
for exclusion and the i_flags, and fix up xfs_iunpin to use igrab before
marking the inode dirty.
SGI-PV: 952967
SGI-Modid: xfs-linux-melb:xfs-kern:26964a
Signed-off-by: David Chinner <dgc@sgi.com>
Signed-off-by: Tim Shimmin <tes@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_iget.c')
-rw-r--r-- | fs/xfs/xfs_iget.c | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 9b9379792f37..b73d216ecaf9 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c | |||
@@ -243,7 +243,9 @@ again: | |||
243 | 243 | ||
244 | XFS_STATS_INC(xs_ig_found); | 244 | XFS_STATS_INC(xs_ig_found); |
245 | 245 | ||
246 | spin_lock(&ip->i_flags_lock); | ||
246 | ip->i_flags &= ~XFS_IRECLAIMABLE; | 247 | ip->i_flags &= ~XFS_IRECLAIMABLE; |
248 | spin_unlock(&ip->i_flags_lock); | ||
247 | version = ih->ih_version; | 249 | version = ih->ih_version; |
248 | read_unlock(&ih->ih_lock); | 250 | read_unlock(&ih->ih_lock); |
249 | xfs_ihash_promote(ih, ip, version); | 251 | xfs_ihash_promote(ih, ip, version); |
@@ -297,7 +299,9 @@ finish_inode: | |||
297 | if (lock_flags != 0) | 299 | if (lock_flags != 0) |
298 | xfs_ilock(ip, lock_flags); | 300 | xfs_ilock(ip, lock_flags); |
299 | 301 | ||
302 | spin_lock(&ip->i_flags_lock); | ||
300 | ip->i_flags &= ~XFS_ISTALE; | 303 | ip->i_flags &= ~XFS_ISTALE; |
304 | spin_unlock(&ip->i_flags_lock); | ||
301 | 305 | ||
302 | vn_trace_exit(vp, "xfs_iget.found", | 306 | vn_trace_exit(vp, "xfs_iget.found", |
303 | (inst_t *)__return_address); | 307 | (inst_t *)__return_address); |
@@ -367,7 +371,9 @@ finish_inode: | |||
367 | ih->ih_next = ip; | 371 | ih->ih_next = ip; |
368 | ip->i_udquot = ip->i_gdquot = NULL; | 372 | ip->i_udquot = ip->i_gdquot = NULL; |
369 | ih->ih_version++; | 373 | ih->ih_version++; |
374 | spin_lock(&ip->i_flags_lock); | ||
370 | ip->i_flags |= XFS_INEW; | 375 | ip->i_flags |= XFS_INEW; |
376 | spin_unlock(&ip->i_flags_lock); | ||
371 | 377 | ||
372 | write_unlock(&ih->ih_lock); | 378 | write_unlock(&ih->ih_lock); |
373 | 379 | ||