aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2022-12-15 20:06:26 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2023-01-24 05:21:22 +0000
commitcc17f41e07925875ce5d004c287c4ef1f4f543be (patch)
tree0ab89cc53b9ba228298683cd55ed1071cd29fe82
parentc45a44b20ae078144454a63ca82861581c456635 (diff)
downloadsrc-cc17f41e07925875ce5d004c287c4ef1f4f543be.tar.gz
src-cc17f41e07925875ce5d004c287c4ef1f4f543be.zip
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 (cherry picked from commit 69542f26820b7edb8351398b36edda5299c1db56)
-rw-r--r--sys/kern/uipc_ktls.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/sys/kern/uipc_ktls.c b/sys/kern/uipc_ktls.c
index e3f84171a976..711b38ec7f99 100644
--- a/sys/kern/uipc_ktls.c
+++ b/sys/kern/uipc_ktls.c
@@ -1866,6 +1866,27 @@ tls13_find_record_type(struct ktls_session *tls, struct mbuf *m, int tls_len,
}
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)
{
char tls_header[MBUF_PEXT_HDR_LEN];
@@ -1921,10 +1942,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_usrreqs->pru_abort(so);
- so->so_error = error;
- CURVNET_RESTORE();
+ ktls_drop(so, error);
goto deref;
}
@@ -2331,8 +2349,7 @@ retry_page:
if (error == 0) {
(void)(*so->so_proto->pr_usrreqs->pru_ready)(so, top, npages);
} else {
- so->so_proto->pr_usrreqs->pru_abort(so);
- so->so_error = EIO;
+ ktls_drop(so, EIO);
mb_free_notready(top, total_pages);
}