Commit baff4b7b authored by Trond Myklebust's avatar Trond Myklebust Committed by Zheng Zengkai
Browse files

SUNRPC: Close a race with transport setup and module put

hulk inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I4IL3P


CVE: NA

--------------------------------

After we've looked up the transport module, we need to ensure it can't
go away until we've finished running the transport setup code.

Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: default avatarLu Wei <luwei32@huawei.com>
Reviewed-by: default avatarWei Yongjun <weiyongjun1@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parent a41f60f0
Loading
Loading
Loading
Loading
+33 −11
Original line number Diff line number Diff line
@@ -158,6 +158,32 @@ xprt_class_release(const struct xprt_class *t)
	module_put(t->owner);
}

static const struct xprt_class *
xprt_class_find_by_ident_locked(int ident)
{
	const struct xprt_class *t;

	list_for_each_entry(t, &xprt_list, list) {
		if (t->ident != ident)
			continue;
		if (!try_module_get(t->owner))
			continue;
		return t;
	}
	return NULL;
}

static const struct xprt_class *
xprt_class_find_by_ident(int ident)
{
	const struct xprt_class *t;

	spin_lock(&xprt_list_lock);
	t = xprt_class_find_by_ident_locked(ident);
	spin_unlock(&xprt_list_lock);
	return t;
}

static const struct xprt_class *
xprt_class_find_by_netid_locked(const char *netid)
{
@@ -1959,21 +1985,17 @@ static void xprt_init(struct rpc_xprt *xprt, struct net *net)
struct rpc_xprt *xprt_create_transport(struct xprt_create *args)
{
	struct rpc_xprt	*xprt;
	struct xprt_class *t;
	const struct xprt_class *t;

	spin_lock(&xprt_list_lock);
	list_for_each_entry(t, &xprt_list, list) {
		if (t->ident == args->ident) {
			spin_unlock(&xprt_list_lock);
			goto found;
		}
	}
	spin_unlock(&xprt_list_lock);
	t = xprt_class_find_by_ident(args->ident);
	if (!t) {
		dprintk("RPC: transport (%d) not supported\n", args->ident);
		return ERR_PTR(-EIO);
	}

found:
	xprt = t->setup(args);
	xprt_class_release(t);

	if (IS_ERR(xprt))
		goto out;
	if (args->flags & XPRT_CREATE_NO_IDLE_TIMEOUT)