Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b9fbe709 authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller
Browse files

netlink: Use random autobind rover



Currently we use a global rover to select a port ID that is unique.
This used to work consistently when it was protected with a global
lock.  However as we're now lockless, the global rover can exhibit
pathological behaviour should multiple threads all stomp on it at
the same time.

Granted this will eventually resolve itself but the process is
suboptimal.

This patch replaces the global rover with a pseudorandom starting
point to avoid this issue.

Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent de133464
Loading
Loading
Loading
Loading
+10 −6
Original line number Diff line number Diff line
@@ -1299,20 +1299,24 @@ static int netlink_autobind(struct socket *sock)
	struct netlink_table *table = &nl_table[sk->sk_protocol];
	s32 portid = task_tgid_vnr(current);
	int err;
	static s32 rover = -4097;
	s32 rover = -4096;
	bool ok;

retry:
	cond_resched();
	rcu_read_lock();
	if (__netlink_lookup(table, portid, net)) {
	ok = !__netlink_lookup(table, portid, net);
	rcu_read_unlock();
	if (!ok) {
		/* Bind collision, search negative portid values. */
		portid = rover--;
		if (rover > -4097)
		if (rover == -4096)
			/* rover will be in range [S32_MIN, -4097] */
			rover = S32_MIN + prandom_u32_max(-4096 - S32_MIN);
		else if (rover >= -4096)
			rover = -4097;
		rcu_read_unlock();
		portid = rover--;
		goto retry;
	}
	rcu_read_unlock();

	err = netlink_insert(sk, portid);
	if (err == -EADDRINUSE)