diff options
author | Tom Herbert <tom@herbertland.com> | 2016-08-23 14:55:31 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-08-23 19:23:12 -0400 |
commit | 1616b38f201945f5fc88aa09b525e3625777aa7c (patch) | |
tree | 0d5f890a7b0d21fa7c4d7580a70e0bfcae2c0738 | |
parent | cff6a334e63420e95ec40dc7fcdc0b8258615760 (diff) |
kcm: Fix locking issue
Lock the lower socket in kcm_unattach. Release during call to strp_done
since that function cancels the RX timers and work queue with sync.
Also added some status information in psock reporting.
Signed-off-by: Tom Herbert <tom@herbertland.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/kcm/kcmproc.c | 20 | ||||
-rw-r--r-- | net/kcm/kcmsock.c | 13 |
2 files changed, 23 insertions, 10 deletions
diff --git a/net/kcm/kcmproc.c b/net/kcm/kcmproc.c index 47e445364f4f..bf75c9231cca 100644 --- a/net/kcm/kcmproc.c +++ b/net/kcm/kcmproc.c | |||
@@ -173,14 +173,24 @@ static void kcm_format_psock(struct kcm_psock *psock, struct seq_file *seq, | |||
173 | if (psock->strp.rx_stopped) | 173 | if (psock->strp.rx_stopped) |
174 | seq_puts(seq, "RxStop "); | 174 | seq_puts(seq, "RxStop "); |
175 | 175 | ||
176 | if (psock->strp.rx_paused) | ||
177 | seq_puts(seq, "RxPause "); | ||
178 | |||
179 | if (psock->tx_kcm) | 176 | if (psock->tx_kcm) |
180 | seq_printf(seq, "Rsvd-%d ", psock->tx_kcm->index); | 177 | seq_printf(seq, "Rsvd-%d ", psock->tx_kcm->index); |
181 | 178 | ||
182 | if (psock->ready_rx_msg) | 179 | if (!psock->strp.rx_paused && !psock->ready_rx_msg) { |
183 | seq_puts(seq, "RdyRx "); | 180 | if (psock->sk->sk_receive_queue.qlen) { |
181 | if (psock->strp.rx_need_bytes) | ||
182 | seq_printf(seq, "RxWait=%u ", | ||
183 | psock->strp.rx_need_bytes); | ||
184 | else | ||
185 | seq_printf(seq, "RxWait "); | ||
186 | } | ||
187 | } else { | ||
188 | if (psock->strp.rx_paused) | ||
189 | seq_puts(seq, "RxPause "); | ||
190 | |||
191 | if (psock->ready_rx_msg) | ||
192 | seq_puts(seq, "RdyRx "); | ||
193 | } | ||
184 | 194 | ||
185 | seq_puts(seq, "\n"); | 195 | seq_puts(seq, "\n"); |
186 | } | 196 | } |
diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c index eedbe404af35..eb731cacc325 100644 --- a/net/kcm/kcmsock.c +++ b/net/kcm/kcmsock.c | |||
@@ -1477,12 +1477,13 @@ out: | |||
1477 | return err; | 1477 | return err; |
1478 | } | 1478 | } |
1479 | 1479 | ||
1480 | /* Lower socket lock held */ | ||
1481 | static void kcm_unattach(struct kcm_psock *psock) | 1480 | static void kcm_unattach(struct kcm_psock *psock) |
1482 | { | 1481 | { |
1483 | struct sock *csk = psock->sk; | 1482 | struct sock *csk = psock->sk; |
1484 | struct kcm_mux *mux = psock->mux; | 1483 | struct kcm_mux *mux = psock->mux; |
1485 | 1484 | ||
1485 | lock_sock(csk); | ||
1486 | |||
1486 | /* Stop getting callbacks from TCP socket. After this there should | 1487 | /* Stop getting callbacks from TCP socket. After this there should |
1487 | * be no way to reserve a kcm for this psock. | 1488 | * be no way to reserve a kcm for this psock. |
1488 | */ | 1489 | */ |
@@ -1514,7 +1515,10 @@ static void kcm_unattach(struct kcm_psock *psock) | |||
1514 | 1515 | ||
1515 | write_unlock_bh(&csk->sk_callback_lock); | 1516 | write_unlock_bh(&csk->sk_callback_lock); |
1516 | 1517 | ||
1518 | /* Call strp_done without sock lock */ | ||
1519 | release_sock(csk); | ||
1517 | strp_done(&psock->strp); | 1520 | strp_done(&psock->strp); |
1521 | lock_sock(csk); | ||
1518 | 1522 | ||
1519 | bpf_prog_put(psock->bpf_prog); | 1523 | bpf_prog_put(psock->bpf_prog); |
1520 | 1524 | ||
@@ -1564,6 +1568,8 @@ no_reserved: | |||
1564 | fput(csk->sk_socket->file); | 1568 | fput(csk->sk_socket->file); |
1565 | kmem_cache_free(kcm_psockp, psock); | 1569 | kmem_cache_free(kcm_psockp, psock); |
1566 | } | 1570 | } |
1571 | |||
1572 | release_sock(csk); | ||
1567 | } | 1573 | } |
1568 | 1574 | ||
1569 | static int kcm_unattach_ioctl(struct socket *sock, struct kcm_unattach *info) | 1575 | static int kcm_unattach_ioctl(struct socket *sock, struct kcm_unattach *info) |
@@ -1749,11 +1755,8 @@ static void release_mux(struct kcm_mux *mux) | |||
1749 | /* Release psocks */ | 1755 | /* Release psocks */ |
1750 | list_for_each_entry_safe(psock, tmp_psock, | 1756 | list_for_each_entry_safe(psock, tmp_psock, |
1751 | &mux->psocks, psock_list) { | 1757 | &mux->psocks, psock_list) { |
1752 | if (!WARN_ON(psock->unattaching)) { | 1758 | if (!WARN_ON(psock->unattaching)) |
1753 | lock_sock(psock->strp.sk); | ||
1754 | kcm_unattach(psock); | 1759 | kcm_unattach(psock); |
1755 | release_sock(psock->strp.sk); | ||
1756 | } | ||
1757 | } | 1760 | } |
1758 | 1761 | ||
1759 | if (WARN_ON(mux->psocks_cnt)) | 1762 | if (WARN_ON(mux->psocks_cnt)) |