Skip to content

Commit 34e5b01

Browse files
lxindavem330
authored andcommitted
sctp: delay auto_asconf init until binding the first addr
As Or Cohen described: If sctp_destroy_sock is called without sock_net(sk)->sctp.addr_wq_lock held and sp->do_auto_asconf is true, then an element is removed from the auto_asconf_splist without any proper locking. This can happen in the following functions: 1. In sctp_accept, if sctp_sock_migrate fails. 2. In inet_create or inet6_create, if there is a bpf program attached to BPF_CGROUP_INET_SOCK_CREATE which denies creation of the sctp socket. This patch is to fix it by moving the auto_asconf init out of sctp_init_sock(), by which inet_create()/inet6_create() won't need to operate it in sctp_destroy_sock() when calling sk_common_release(). It also makes more sense to do auto_asconf init while binding the first addr, as auto_asconf actually requires an ANY addr bind, see it in sctp_addr_wq_timeout_handler(). This addresses CVE-2021-23133. Fixes: 6102365 ("bpf: Add new cgroup attach type to enable sock modifications") Reported-by: Or Cohen <[email protected]> Signed-off-by: Xin Long <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 01bfe5e commit 34e5b01

File tree

1 file changed

+17
-14
lines changed

1 file changed

+17
-14
lines changed

net/sctp/socket.c

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,18 @@ static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt,
357357
return af;
358358
}
359359

360+
static void sctp_auto_asconf_init(struct sctp_sock *sp)
361+
{
362+
struct net *net = sock_net(&sp->inet.sk);
363+
364+
if (net->sctp.default_auto_asconf) {
365+
spin_lock(&net->sctp.addr_wq_lock);
366+
list_add_tail(&sp->auto_asconf_list, &net->sctp.auto_asconf_splist);
367+
spin_unlock(&net->sctp.addr_wq_lock);
368+
sp->do_auto_asconf = 1;
369+
}
370+
}
371+
360372
/* Bind a local address either to an endpoint or to an association. */
361373
static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
362374
{
@@ -418,8 +430,10 @@ static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
418430
return -EADDRINUSE;
419431

420432
/* Refresh ephemeral port. */
421-
if (!bp->port)
433+
if (!bp->port) {
422434
bp->port = inet_sk(sk)->inet_num;
435+
sctp_auto_asconf_init(sp);
436+
}
423437

424438
/* Add the address to the bind address list.
425439
* Use GFP_ATOMIC since BHs will be disabled.
@@ -4993,19 +5007,6 @@ static int sctp_init_sock(struct sock *sk)
49935007
sk_sockets_allocated_inc(sk);
49945008
sock_prot_inuse_add(net, sk->sk_prot, 1);
49955009

4996-
/* Nothing can fail after this block, otherwise
4997-
* sctp_destroy_sock() will be called without addr_wq_lock held
4998-
*/
4999-
if (net->sctp.default_auto_asconf) {
5000-
spin_lock(&sock_net(sk)->sctp.addr_wq_lock);
5001-
list_add_tail(&sp->auto_asconf_list,
5002-
&net->sctp.auto_asconf_splist);
5003-
sp->do_auto_asconf = 1;
5004-
spin_unlock(&sock_net(sk)->sctp.addr_wq_lock);
5005-
} else {
5006-
sp->do_auto_asconf = 0;
5007-
}
5008-
50095010
local_bh_enable();
50105011

50115012
return 0;
@@ -9401,6 +9402,8 @@ static int sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
94019402
return err;
94029403
}
94039404

9405+
sctp_auto_asconf_init(newsp);
9406+
94049407
/* Move any messages in the old socket's receive queue that are for the
94059408
* peeled off association to the new socket's receive queue.
94069409
*/

0 commit comments

Comments
 (0)