aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Herbert <tom@herbertland.com>2016-08-23 14:55:31 -0400
committerDavid S. Miller <davem@davemloft.net>2016-08-23 19:23:12 -0400
commit1616b38f201945f5fc88aa09b525e3625777aa7c (patch)
tree0d5f890a7b0d21fa7c4d7580a70e0bfcae2c0738
parentcff6a334e63420e95ec40dc7fcdc0b8258615760 (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.c20
-rw-r--r--net/kcm/kcmsock.c13
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 */
1481static void kcm_unattach(struct kcm_psock *psock) 1480static 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
1569static int kcm_unattach_ioctl(struct socket *sock, struct kcm_unattach *info) 1575static 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))