xfs: fix tmpfile/selinux deadlock and initialize security
xfstests generic/004 reproduces an ilock deadlock using the tmpfile
interface when selinux is enabled. This occurs because
xfs_create_tmpfile() takes the ilock and then calls d_tmpfile(). The
latter eventually calls into xfs_xattr_get() which attempts to get the
lock again. E.g.:
xfs_io D
ffffffff81c134c0 4096 3561 3560 0x00000080
ffff8801176a1a68 0000000000000046 ffff8800b401b540 ffff8801176a1fd8
00000000001d5800 00000000001d5800 ffff8800b401b540 ffff8800b401b540
ffff8800b73a6bd0 fffffffeffffffff ffff8800b73a6bd8 ffff8800b5ddb480
Call Trace:
[<
ffffffff8177f969>] schedule+0x29/0x70
[<
ffffffff81783a65>] rwsem_down_read_failed+0xc5/0x120
[<
ffffffffa05aa97f>] ? xfs_ilock_attr_map_shared+0x1f/0x50 [xfs]
[<
ffffffff813b3434>] call_rwsem_down_read_failed+0x14/0x30
[<
ffffffff810ed179>] ? down_read_nested+0x89/0xa0
[<
ffffffffa05aa7f2>] ? xfs_ilock+0x122/0x250 [xfs]
[<
ffffffffa05aa7f2>] xfs_ilock+0x122/0x250 [xfs]
[<
ffffffffa05aa97f>] xfs_ilock_attr_map_shared+0x1f/0x50 [xfs]
[<
ffffffffa05701d0>] xfs_attr_get+0x90/0xe0 [xfs]
[<
ffffffffa0565e07>] xfs_xattr_get+0x37/0x50 [xfs]
[<
ffffffff8124842f>] generic_getxattr+0x4f/0x70
[<
ffffffff8133fd9e>] inode_doinit_with_dentry+0x1ae/0x650
[<
ffffffff81340e0c>] selinux_d_instantiate+0x1c/0x20
[<
ffffffff813351bb>] security_d_instantiate+0x1b/0x30
[<
ffffffff81237db0>] d_instantiate+0x50/0x70
[<
ffffffff81237e85>] d_tmpfile+0xb5/0xc0
[<
ffffffffa05add02>] xfs_create_tmpfile+0x362/0x410 [xfs]
[<
ffffffffa0559ac8>] xfs_vn_tmpfile+0x18/0x20 [xfs]
[<
ffffffff81230388>] path_openat+0x228/0x6a0
[<
ffffffff810230f9>] ? sched_clock+0x9/0x10
[<
ffffffff8105a427>] ? kvm_clock_read+0x27/0x40
[<
ffffffff8124054f>] ? __alloc_fd+0xaf/0x1f0
[<
ffffffff8123101a>] do_filp_open+0x3a/0x90
[<
ffffffff817845e7>] ? _raw_spin_unlock+0x27/0x40
[<
ffffffff8124054f>] ? __alloc_fd+0xaf/0x1f0
[<
ffffffff8121e3ce>] do_sys_open+0x12e/0x210
[<
ffffffff8121e4ce>] SyS_open+0x1e/0x20
[<
ffffffff8178eda9>] system_call_fastpath+0x16/0x1b
xfs_vn_tmpfile() also fails to initialize security on the newly created
inode.
Pull the d_tmpfile() call up into xfs_vn_tmpfile() after the transaction
has been committed and the inode unlocked. Also, initialize security on
the inode based on the parent directory provided via the tmpfile call.
Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dave Chinner <david@fromorbit.com>