2017-06-08 04:48:44

by Nicholas A. Bellinger

[permalink] [raw]
Subject: [PATCH] configfs: Fix race between create_link and configfs_rmdir

From: Nicholas Bellinger <[email protected]>

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: Bryant G. Ly <[email protected]>
Tested-by: Bryant G. Ly <[email protected]>
Cc: Bryant G. Ly <[email protected]>
Cc: Christoph Hellwig <[email protected]>
Cc: Joel Becker <[email protected]>
Signed-off-by: Nicholas Bellinger <[email protected]>
---
fs/configfs/symlink.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c
index a6ab012..c8aabba 100644
--- a/fs/configfs/symlink.c
+++ b/fs/configfs/symlink.c
@@ -83,14 +83,13 @@ static int create_link(struct config_item *parent_item,
ret = -ENOMEM;
sl = kmalloc(sizeof(struct configfs_symlink), GFP_KERNEL);
if (sl) {
- sl->sl_target = config_item_get(item);
spin_lock(&configfs_dirent_lock);
if (target_sd->s_type & CONFIGFS_USET_DROPPING) {
spin_unlock(&configfs_dirent_lock);
- config_item_put(item);
kfree(sl);
return -ENOENT;
}
+ sl->sl_target = config_item_get(item);
list_add(&sl->sl_list, &target_sd->s_links);
spin_unlock(&configfs_dirent_lock);
ret = configfs_create_link(sl, parent_item->ci_dentry,
--
1.9.1


2017-06-08 07:21:33

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH] configfs: Fix race between create_link and configfs_rmdir

Thanks Nic,

applied to the configfs-for-next tree. I'm not entirely sure if we
should bother adding this to 4.12 or if it hits rarely enough?

2017-06-08 12:34:11

by Bryant G. Ly

[permalink] [raw]
Subject: Re: [PATCH] configfs: Fix race between create_link and configfs_rmdir


> Thanks Nic,
>
> applied to the configfs-for-next tree. I'm not entirely sure if we
> should bother adding this to 4.12 or if it hits rarely enough?
>
It hits for us pretty often when we have a GPFS setup with 10 hosts and 1k+ vms.

That is how we discovered the bug in the first place.

-Bryant

2017-06-09 07:05:09

by Nicholas A. Bellinger

[permalink] [raw]
Subject: Re: [PATCH] configfs: Fix race between create_link and configfs_rmdir

On Thu, 2017-06-08 at 07:34 -0500, Bryant G. Ly wrote:
> > Thanks Nic,
> >
> > applied to the configfs-for-next tree. I'm not entirely sure if we
> > should bother adding this to 4.12 or if it hits rarely enough?
> >
> It hits for us pretty often when we have a GPFS setup with 10 hosts and 1k+ vms.
>
> That is how we discovered the bug in the first place.
>

Using a DATERA workload with 1K unique multi-tenant backend devices and
1K unique iscsi-target IQNs per node, I've never tripped across this
particular bug..

However, our userspace built atop rtslib is enforcing tenant shutdown of
individual rmdir(2) of /sys/kernel/config/target/$FABRIC/$WWN/$TPGT/,
before rmdir(2) of /sys/kernel/config/target/core/$HBA/$DEV/ occurs.

Based on Bryant's original backtrace with targetcli, it looks like the
Novalink user-space is not enforcing this requirement across user-space
processes doing fabric port symlink and backend device shutdown.

That said it probably doesn't need a special v4.12-rc PULL, but based on
Bryant's feedback it certainly does deserve a stable CC'.