mirror of
https://github.com/torvalds/linux.git
synced 2024-12-07 19:41:31 +00:00
Merge branch 'tipc-fix-two-race-issues-in-tipc_conn_alloc'
Xin Long says: ==================== tipc: fix two race issues in tipc_conn_alloc The race exists beteen tipc_topsrv_accept() and tipc_conn_close(), one is allocating the con while the other is freeing it and there is no proper lock protecting it. Therefore, a null-pointer-defer and a use-after-free may be triggered, see details on each patch. ==================== Link: https://lore.kernel.org/r/cover.1668807842.git.lucien.xin@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
3349c272de
@ -176,7 +176,7 @@ static void tipc_conn_close(struct tipc_conn *con)
|
||||
conn_put(con);
|
||||
}
|
||||
|
||||
static struct tipc_conn *tipc_conn_alloc(struct tipc_topsrv *s)
|
||||
static struct tipc_conn *tipc_conn_alloc(struct tipc_topsrv *s, struct socket *sock)
|
||||
{
|
||||
struct tipc_conn *con;
|
||||
int ret;
|
||||
@ -202,10 +202,12 @@ static struct tipc_conn *tipc_conn_alloc(struct tipc_topsrv *s)
|
||||
}
|
||||
con->conid = ret;
|
||||
s->idr_in_use++;
|
||||
spin_unlock_bh(&s->idr_lock);
|
||||
|
||||
set_bit(CF_CONNECTED, &con->flags);
|
||||
con->server = s;
|
||||
con->sock = sock;
|
||||
conn_get(con);
|
||||
spin_unlock_bh(&s->idr_lock);
|
||||
|
||||
return con;
|
||||
}
|
||||
@ -467,7 +469,7 @@ static void tipc_topsrv_accept(struct work_struct *work)
|
||||
ret = kernel_accept(lsock, &newsock, O_NONBLOCK);
|
||||
if (ret < 0)
|
||||
return;
|
||||
con = tipc_conn_alloc(srv);
|
||||
con = tipc_conn_alloc(srv, newsock);
|
||||
if (IS_ERR(con)) {
|
||||
ret = PTR_ERR(con);
|
||||
sock_release(newsock);
|
||||
@ -479,11 +481,11 @@ static void tipc_topsrv_accept(struct work_struct *work)
|
||||
newsk->sk_data_ready = tipc_conn_data_ready;
|
||||
newsk->sk_write_space = tipc_conn_write_space;
|
||||
newsk->sk_user_data = con;
|
||||
con->sock = newsock;
|
||||
write_unlock_bh(&newsk->sk_callback_lock);
|
||||
|
||||
/* Wake up receive process in case of 'SYN+' message */
|
||||
newsk->sk_data_ready(newsk);
|
||||
conn_put(con);
|
||||
}
|
||||
}
|
||||
|
||||
@ -577,17 +579,17 @@ bool tipc_topsrv_kern_subscr(struct net *net, u32 port, u32 type, u32 lower,
|
||||
sub.filter = filter;
|
||||
*(u64 *)&sub.usr_handle = (u64)port;
|
||||
|
||||
con = tipc_conn_alloc(tipc_topsrv(net));
|
||||
con = tipc_conn_alloc(tipc_topsrv(net), NULL);
|
||||
if (IS_ERR(con))
|
||||
return false;
|
||||
|
||||
*conid = con->conid;
|
||||
con->sock = NULL;
|
||||
rc = tipc_conn_rcv_sub(tipc_topsrv(net), con, &sub);
|
||||
if (rc >= 0)
|
||||
return true;
|
||||
if (rc)
|
||||
conn_put(con);
|
||||
|
||||
conn_put(con);
|
||||
return false;
|
||||
return !rc;
|
||||
}
|
||||
|
||||
void tipc_topsrv_kern_unsubscr(struct net *net, int conid)
|
||||
|
Loading…
Reference in New Issue
Block a user