Commit 4d54cc32 authored by Florian Westphal's avatar Florian Westphal Committed by David S. Miller
Browse files

mptcp: avoid lock_fast usage in accept path



Once event support is added this may need to allocate memory while msk
lock is held with softirqs disabled.

Not using lock_fast also allows to do the allocation with GFP_KERNEL.

Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarMat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6c714f1b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
 */
struct genl_multicast_group {
	char			name[GENL_NAMSIZ];
	u8			flags;
};

struct genl_ops;
+2 −3
Original line number Diff line number Diff line
@@ -3260,9 +3260,8 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock,
		struct mptcp_sock *msk = mptcp_sk(newsock->sk);
		struct mptcp_subflow_context *subflow;
		struct sock *newsk = newsock->sk;
		bool slowpath;

		slowpath = lock_sock_fast(newsk);
		lock_sock(newsk);

		/* PM/worker can now acquire the first subflow socket
		 * lock without racing with listener queue cleanup,
@@ -3288,7 +3287,7 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock,
			if (!ssk->sk_socket)
				mptcp_sock_graft(ssk, newsock);
		}
		unlock_sock_fast(newsk, slowpath);
		release_sock(newsk);
	}

	if (inet_csk_listen_poll(ssock->sk))
+32 −0
Original line number Diff line number Diff line
@@ -1360,11 +1360,43 @@ static struct genl_family genl_ctrl __ro_after_init = {
	.netnsok = true,
};

static int genl_bind(struct net *net, int group)
{
	const struct genl_family *family;
	unsigned int id;
	int ret = 0;

	genl_lock_all();

	idr_for_each_entry(&genl_fam_idr, family, id) {
		const struct genl_multicast_group *grp;
		int i;

		if (family->n_mcgrps == 0)
			continue;

		i = group - family->mcgrp_offset;
		if (i < 0 || i >= family->n_mcgrps)
			continue;

		grp = &family->mcgrps[i];
		if ((grp->flags & GENL_UNS_ADMIN_PERM) &&
		    !ns_capable(net->user_ns, CAP_NET_ADMIN))
			ret = -EPERM;

		break;
	}

	genl_unlock_all();
	return ret;
}

static int __net_init genl_pernet_init(struct net *net)
{
	struct netlink_kernel_cfg cfg = {
		.input		= genl_rcv,
		.flags		= NL_CFG_F_NONROOT_RECV,
		.bind		= genl_bind,
	};

	/* we'll bump the group number right afterwards */