Commit 88d1d76d authored by David S. Miller's avatar David S. Miller

Merge branch 'kcm-fix-two-syzcaller-issues'

Tom Herbert says:

====================
kcm: fix two syzcaller issues

In this patch set:

- Don't allow attaching non-TCP or listener sockets to a KCM mux.
- In kcm_attach Check if sk_user_data is already set. This is
  under lock to avoid race conditions. More work is need to make
  all of the users of sk_user_data to use the same locking.

- v2
  Remove unncessary check for not PF_KCM in kcm_attach (suggested by
  Guillaume Nault)
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d3303a65 e5571240
...@@ -1387,8 +1387,13 @@ static int kcm_attach(struct socket *sock, struct socket *csock, ...@@ -1387,8 +1387,13 @@ static int kcm_attach(struct socket *sock, struct socket *csock,
if (!csk) if (!csk)
return -EINVAL; return -EINVAL;
/* We must prevent loops or risk deadlock ! */ /* Only allow TCP sockets to be attached for now */
if (csk->sk_family == PF_KCM) if ((csk->sk_family != AF_INET && csk->sk_family != AF_INET6) ||
csk->sk_protocol != IPPROTO_TCP)
return -EOPNOTSUPP;
/* Don't allow listeners or closed sockets */
if (csk->sk_state == TCP_LISTEN || csk->sk_state == TCP_CLOSE)
return -EOPNOTSUPP; return -EOPNOTSUPP;
psock = kmem_cache_zalloc(kcm_psockp, GFP_KERNEL); psock = kmem_cache_zalloc(kcm_psockp, GFP_KERNEL);
...@@ -1405,9 +1410,18 @@ static int kcm_attach(struct socket *sock, struct socket *csock, ...@@ -1405,9 +1410,18 @@ static int kcm_attach(struct socket *sock, struct socket *csock,
return err; return err;
} }
sock_hold(csk);
write_lock_bh(&csk->sk_callback_lock); write_lock_bh(&csk->sk_callback_lock);
/* Check if sk_user_data is aready by KCM or someone else.
* Must be done under lock to prevent race conditions.
*/
if (csk->sk_user_data) {
write_unlock_bh(&csk->sk_callback_lock);
strp_done(&psock->strp);
kmem_cache_free(kcm_psockp, psock);
return -EALREADY;
}
psock->save_data_ready = csk->sk_data_ready; psock->save_data_ready = csk->sk_data_ready;
psock->save_write_space = csk->sk_write_space; psock->save_write_space = csk->sk_write_space;
psock->save_state_change = csk->sk_state_change; psock->save_state_change = csk->sk_state_change;
...@@ -1415,8 +1429,11 @@ static int kcm_attach(struct socket *sock, struct socket *csock, ...@@ -1415,8 +1429,11 @@ static int kcm_attach(struct socket *sock, struct socket *csock,
csk->sk_data_ready = psock_data_ready; csk->sk_data_ready = psock_data_ready;
csk->sk_write_space = psock_write_space; csk->sk_write_space = psock_write_space;
csk->sk_state_change = psock_state_change; csk->sk_state_change = psock_state_change;
write_unlock_bh(&csk->sk_callback_lock); write_unlock_bh(&csk->sk_callback_lock);
sock_hold(csk);
/* Finished initialization, now add the psock to the MUX. */ /* Finished initialization, now add the psock to the MUX. */
spin_lock_bh(&mux->lock); spin_lock_bh(&mux->lock);
head = &mux->psocks; head = &mux->psocks;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment