ktls: Close a race with setting so_error when dropping a connection.
pr_abort calls tcp_usr_abort which calls tcp_drop with ECONNABORTED. After pr_abort returns, the so_error is then set to a more specific error. However, a reader can observe and return the ECONNABORTED error before so_error is set to the desired error value. This is resulting in spurious test failures of recently added tests for invalid conditions such as invalid headers. To fix, refactor the code to abort a connection to call tcp_drop directly with the desired error value. ktls_reset_send_tag already calls tcp_drop directly when it aborts a connection due to an error. Reviewed by: gallatin Reported by: CI (jenkins), gallatin, olivier Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D37692
This commit is contained in:
parent
883d1742d3
commit
69542f2682
@ -2301,6 +2301,27 @@ ktls_resync_ifnet(struct socket *so, uint32_t tls_len, uint64_t tls_rcd_num)
|
||||
return (mst->sw->snd_tag_modify(mst, ¶ms));
|
||||
}
|
||||
|
||||
static void
|
||||
ktls_drop(struct socket *so, int error)
|
||||
{
|
||||
struct epoch_tracker et;
|
||||
struct inpcb *inp = sotoinpcb(so);
|
||||
struct tcpcb *tp;
|
||||
|
||||
NET_EPOCH_ENTER(et);
|
||||
INP_WLOCK(inp);
|
||||
if (!(inp->inp_flags & INP_DROPPED)) {
|
||||
tp = intotcpcb(inp);
|
||||
CURVNET_SET(inp->inp_vnet);
|
||||
tp = tcp_drop(tp, error);
|
||||
CURVNET_RESTORE();
|
||||
if (tp != NULL)
|
||||
INP_WUNLOCK(inp);
|
||||
} else
|
||||
INP_WUNLOCK(inp);
|
||||
NET_EPOCH_EXIT(et);
|
||||
}
|
||||
|
||||
static void
|
||||
ktls_decrypt(struct socket *so)
|
||||
{
|
||||
@ -2358,10 +2379,7 @@ ktls_decrypt(struct socket *so)
|
||||
SOCKBUF_UNLOCK(sb);
|
||||
counter_u64_add(ktls_offload_corrupted_records, 1);
|
||||
|
||||
CURVNET_SET(so->so_vnet);
|
||||
so->so_proto->pr_abort(so);
|
||||
so->so_error = error;
|
||||
CURVNET_RESTORE();
|
||||
ktls_drop(so, error);
|
||||
goto deref;
|
||||
}
|
||||
|
||||
@ -2887,8 +2905,7 @@ ktls_encrypt(struct ktls_wq *wq, struct mbuf *top)
|
||||
if (error == 0) {
|
||||
(void)so->so_proto->pr_ready(so, top, npages);
|
||||
} else {
|
||||
so->so_proto->pr_abort(so);
|
||||
so->so_error = EIO;
|
||||
ktls_drop(so, EIO);
|
||||
mb_free_notready(top, total_pages);
|
||||
}
|
||||
|
||||
@ -2931,8 +2948,7 @@ ktls_encrypt_cb(struct ktls_ocf_encrypt_state *state, int error)
|
||||
if (error == 0) {
|
||||
(void)so->so_proto->pr_ready(so, m, npages);
|
||||
} else {
|
||||
so->so_proto->pr_abort(so);
|
||||
so->so_error = EIO;
|
||||
ktls_drop(so, EIO);
|
||||
mb_free_notready(m, npages);
|
||||
}
|
||||
|
||||
@ -2996,8 +3012,7 @@ ktls_encrypt_async(struct ktls_wq *wq, struct mbuf *top)
|
||||
|
||||
CURVNET_SET(so->so_vnet);
|
||||
if (error != 0) {
|
||||
so->so_proto->pr_abort(so);
|
||||
so->so_error = EIO;
|
||||
ktls_drop(so, EIO);
|
||||
mb_free_notready(m, total_pages - npages);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user