diff options
author | David S. Miller <davem@davemloft.net> | 2018-01-24 15:54:31 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-01-24 15:54:31 -0500 |
commit | 88d1d76dca25b135657eda6b93eb1bdbde519d0f (patch) | |
tree | 1541ccbaf77a4b034f515865927e175bb7e00bc0 | |
parent | d3303a65a00c94372ddab831570647488e6c06e2 (diff) | |
parent | e5571240236c5652f3e079b1d5866716a7ad819c (diff) |
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: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/kcm/kcmsock.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c index d4e98f20fc2a..4a8d407f8902 100644 --- a/net/kcm/kcmsock.c +++ b/net/kcm/kcmsock.c | |||
@@ -1387,8 +1387,13 @@ static int kcm_attach(struct socket *sock, struct socket *csock, | |||
1387 | if (!csk) | 1387 | if (!csk) |
1388 | return -EINVAL; | 1388 | return -EINVAL; |
1389 | 1389 | ||
1390 | /* We must prevent loops or risk deadlock ! */ | 1390 | /* Only allow TCP sockets to be attached for now */ |
1391 | if (csk->sk_family == PF_KCM) | 1391 | if ((csk->sk_family != AF_INET && csk->sk_family != AF_INET6) || |
1392 | csk->sk_protocol != IPPROTO_TCP) | ||
1393 | return -EOPNOTSUPP; | ||
1394 | |||
1395 | /* Don't allow listeners or closed sockets */ | ||
1396 | if (csk->sk_state == TCP_LISTEN || csk->sk_state == TCP_CLOSE) | ||
1392 | return -EOPNOTSUPP; | 1397 | return -EOPNOTSUPP; |
1393 | 1398 | ||
1394 | psock = kmem_cache_zalloc(kcm_psockp, GFP_KERNEL); | 1399 | psock = kmem_cache_zalloc(kcm_psockp, GFP_KERNEL); |
@@ -1405,9 +1410,18 @@ static int kcm_attach(struct socket *sock, struct socket *csock, | |||
1405 | return err; | 1410 | return err; |
1406 | } | 1411 | } |
1407 | 1412 | ||
1408 | sock_hold(csk); | ||
1409 | |||
1410 | write_lock_bh(&csk->sk_callback_lock); | 1413 | write_lock_bh(&csk->sk_callback_lock); |
1414 | |||
1415 | /* Check if sk_user_data is aready by KCM or someone else. | ||
1416 | * Must be done under lock to prevent race conditions. | ||
1417 | */ | ||
1418 | if (csk->sk_user_data) { | ||
1419 | write_unlock_bh(&csk->sk_callback_lock); | ||
1420 | strp_done(&psock->strp); | ||
1421 | kmem_cache_free(kcm_psockp, psock); | ||
1422 | return -EALREADY; | ||
1423 | } | ||
1424 | |||
1411 | psock->save_data_ready = csk->sk_data_ready; | 1425 | psock->save_data_ready = csk->sk_data_ready; |
1412 | psock->save_write_space = csk->sk_write_space; | 1426 | psock->save_write_space = csk->sk_write_space; |
1413 | psock->save_state_change = csk->sk_state_change; | 1427 | psock->save_state_change = csk->sk_state_change; |
@@ -1415,8 +1429,11 @@ static int kcm_attach(struct socket *sock, struct socket *csock, | |||
1415 | csk->sk_data_ready = psock_data_ready; | 1429 | csk->sk_data_ready = psock_data_ready; |
1416 | csk->sk_write_space = psock_write_space; | 1430 | csk->sk_write_space = psock_write_space; |
1417 | csk->sk_state_change = psock_state_change; | 1431 | csk->sk_state_change = psock_state_change; |
1432 | |||
1418 | write_unlock_bh(&csk->sk_callback_lock); | 1433 | write_unlock_bh(&csk->sk_callback_lock); |
1419 | 1434 | ||
1435 | sock_hold(csk); | ||
1436 | |||
1420 | /* Finished initialization, now add the psock to the MUX. */ | 1437 | /* Finished initialization, now add the psock to the MUX. */ |
1421 | spin_lock_bh(&mux->lock); | 1438 | spin_lock_bh(&mux->lock); |
1422 | head = &mux->psocks; | 1439 | head = &mux->psocks; |