Commit a1300691 authored by Eric Dumazet's avatar Eric Dumazet Committed by Jakub Kicinski
Browse files

net: rose: lock the socket in rose_bind()



syzbot reported a soft lockup in rose_loopback_timer(),
with a repro calling bind() from multiple threads.

rose_bind() must lock the socket to avoid this issue.

Fixes: 1da177e4 ("Linux-2.6.12-rc2")
Reported-by: default avatar <syzbot+7ff41b5215f0c534534e@syzkaller.appspotmail.com>
Closes: https://lore.kernel.org/netdev/67a0f78d.050a0220.d7c5a.00a0.GAE@google.com/T/#u


Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Acked-by: default avatarPaolo Abeni <pabeni@redhat.com>
Link: https://patch.msgid.link/20250203170838.3521361-1-edumazet@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 028676bb
Loading
Loading
Loading
Loading
+16 −8
Original line number Diff line number Diff line
@@ -701,11 +701,9 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
	struct net_device *dev;
	ax25_address *source;
	ax25_uid_assoc *user;
	int err = -EINVAL;
	int n;

	if (!sock_flag(sk, SOCK_ZAPPED))
		return -EINVAL;

	if (addr_len != sizeof(struct sockaddr_rose) && addr_len != sizeof(struct full_sockaddr_rose))
		return -EINVAL;

@@ -718,8 +716,15 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
	if ((unsigned int) addr->srose_ndigis > ROSE_MAX_DIGIS)
		return -EINVAL;

	if ((dev = rose_dev_get(&addr->srose_addr)) == NULL)
		return -EADDRNOTAVAIL;
	lock_sock(sk);

	if (!sock_flag(sk, SOCK_ZAPPED))
		goto out_release;

	err = -EADDRNOTAVAIL;
	dev = rose_dev_get(&addr->srose_addr);
	if (!dev)
		goto out_release;

	source = &addr->srose_call;

@@ -730,7 +735,8 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
	} else {
		if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) {
			dev_put(dev);
			return -EACCES;
			err = -EACCES;
			goto out_release;
		}
		rose->source_call   = *source;
	}
@@ -753,8 +759,10 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
	rose_insert_socket(sk);

	sock_reset_flag(sk, SOCK_ZAPPED);

	return 0;
	err = 0;
out_release:
	release_sock(sk);
	return err;
}

static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags)