Skip to content
  • Nicholas Bellinger's avatar
    configfs: Fix race between create_link and configfs_rmdir · ba80aa90
    Nicholas Bellinger authored
    
    
    This patch closes a long standing race in configfs between
    the creation of a new symlink in create_link(), while the
    symlink target's config_item is being concurrently removed
    via configfs_rmdir().
    
    This can happen because the symlink target's reference
    is obtained by config_item_get() in create_link() before
    the CONFIGFS_USET_DROPPING bit set by configfs_detach_prep()
    during configfs_rmdir() shutdown is actually checked..
    
    This originally manifested itself on ppc64 on v4.8.y under
    heavy load using ibmvscsi target ports with Novalink API:
    
    [ 7877.289863] rpadlpar_io: slot U8247.22L.212A91A-V1-C8 added
    [ 7879.893760] ------------[ cut here ]------------
    [ 7879.893768] WARNING: CPU: 15 PID: 17585 at ./include/linux/kref.h:46 config_item_get+0x7c/0x90 [configfs]
    [ 7879.893811] CPU: 15 PID: 17585 Comm: targetcli Tainted: G           O 4.8.17-customv2.22 #12
    [ 7879.893812] task: c00000018a0d3400 task.stack: c0000001f3b40000
    [ 7879.893813] NIP: d000000002c664ec LR: d000000002c60980 CTR: c000000000b70870
    [ 7879.893814] REGS: c0000001f3b43810 TRAP: 0700   Tainted: G O     (4.8.17-customv2.22)
    [ 7879.893815] MSR: 8000000000029033 <SF,EE,ME,IR,DR,RI,LE>  CR: 28222242  XER: 00000000
    [ 7879.893820] CFAR: d000000002c664bc SOFTE: 1
                    GPR00: d000000002c60980 c0000001f3b43a90 d000000002c70908 c0000000fbc06820
                    GPR04: c0000001ef1bd900 0000000000000004 0000000000000001 0000000000000000
                    GPR08: 0000000000000000 0000000000000001 d000000002c69560 d000000002c66d80
                    GPR12: c000000000b70870 c00000000e798700 c0000001f3b43ca0 c0000001d4949d40
                    GPR16: c00000014637e1c0 0000000000000000 0000000000000000 c0000000f2392940
                    GPR20: c0000001f3b43b98 0000000000000041 0000000000600000 0000000000000000
                    GPR24: fffffffffffff000 0000000000000000 d000000002c60be0 c0000001f1dac490
                    GPR28: 0000000000000004 0000000000000000 c0000001ef1bd900 c0000000f2392940
    [ 7879.893839] NIP [d000000002c664ec] config_item_get+0x7c/0x90 [configfs]
    [ 7879.893841] LR [d000000002c60980] check_perm+0x80/0x2e0 [configfs]
    [ 7879.893842] Call Trace:
    [ 7879.893844] [c0000001f3b43ac0] [d000000002c60980] check_perm+0x80/0x2e0 [configfs]
    [ 7879.893847] [c0000001f3b43b10] [c000000000329770] do_dentry_open+0x2c0/0x460
    [ 7879.893849] [c0000001f3b43b70] [c000000000344480] path_openat+0x210/0x1490
    [ 7879.893851] [c0000001f3b43c80] [c00000000034708c] do_filp_open+0xfc/0x170
    [ 7879.893853] [c0000001f3b43db0] [c00000000032b5bc] do_sys_open+0x1cc/0x390
    [ 7879.893856] [c0000001f3b43e30] [c000000000009584] system_call+0x38/0xec
    [ 7879.893856] Instruction dump:
    [ 7879.893858] 409d0014 38210030 e8010010 7c0803a6 4e800020 3d220000 e94981e0 892a0000
    [ 7879.893861] 2f890000 409effe0 39200001 992a0000 <0fe00000> 4bffffd0 60000000 60000000
    [ 7879.893866] ---[ end trace 14078f0b3b5ad0aa ]---
    
    To close this race, go ahead and obtain the symlink's target
    config_item reference only after the existing CONFIGFS_USET_DROPPING
    check succeeds.
    
    This way, if configfs_rmdir() wins create_link() will return -ENONET,
    and if create_link() wins configfs_rmdir() will return -EBUSY.
    
    Reported-by: default avatarBryant G. Ly <bryantly@linux.vnet.ibm.com>
    Tested-by: default avatarBryant G. Ly <bryantly@linux.vnet.ibm.com>
    Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
    Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
    Cc: stable@vger.kernel.org
    ba80aa90