aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRick Macklem <rmacklem@FreeBSD.org>2024-04-27 00:55:24 +0000
committerRick Macklem <rmacklem@FreeBSD.org>2024-05-02 01:09:52 +0000
commitf6b902a4117a9893179be4e46c50358d32321301 (patch)
tree73d3ad75d0ddebe84331dc5375375e88aca76f63
parent63b747823bead05837f6893a2f2d38b516bc1e49 (diff)
downloadsrc-f6b902a4117a9893179be4e46c50358d32321301.tar.gz
src-f6b902a4117a9893179be4e46c50358d32321301.zip
krpc: Ref cnt the client structures for TLS upcalls
A crash occurred during testing, where the client structures had already been free'd when the upcall thread tried to lock them. This patch acquires a reference count on both of the structures and these are released when the upcall is done, so that the structures cannot be free'd prematurely. This happened because the testing is done over a very slow vpn. Found during a IETF bakeathon testing event this week. (cherry picked from commit 4ba444de708bada46a88ecac17b2f6c1dc912234)
-rw-r--r--sys/rpc/clnt_vc.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/sys/rpc/clnt_vc.c b/sys/rpc/clnt_vc.c
index b4ddaec3cbdc..cc2471f95e8c 100644
--- a/sys/rpc/clnt_vc.c
+++ b/sys/rpc/clnt_vc.c
@@ -759,6 +759,7 @@ clnt_vc_control(CLIENT *cl, u_int request, void *info)
case CLSET_BACKCHANNEL:
xprt = (SVCXPRT *)info;
if (ct->ct_backchannelxprt == NULL) {
+ SVC_ACQUIRE(xprt);
xprt->xp_p2 = ct;
if (ct->ct_sslrefno != 0)
xprt->xp_tls = RPCTLS_FLAGS_HANDSHAKE;
@@ -772,9 +773,11 @@ clnt_vc_control(CLIENT *cl, u_int request, void *info)
ct->ct_sslusec = *p++;
ct->ct_sslrefno = *p;
if (ct->ct_sslrefno != RPCTLS_REFNO_HANDSHAKE) {
+ /* cl ref cnt is released by clnt_vc_dotlsupcall(). */
+ CLNT_ACQUIRE(cl);
mtx_unlock(&ct->ct_lock);
/* Start the kthread that handles upcalls. */
- error = kthread_add(clnt_vc_dotlsupcall, ct,
+ error = kthread_add(clnt_vc_dotlsupcall, cl,
NULL, NULL, 0, 0, "krpctls%u", thrdnum++);
if (error != 0)
panic("Can't add KRPC thread error %d", error);
@@ -874,6 +877,7 @@ clnt_vc_destroy(CLIENT *cl)
mtx_lock(&ct->ct_lock);
xprt->xp_p2 = NULL;
sx_xunlock(&xprt->xp_lock);
+ SVC_RELEASE(xprt);
}
if (ct->ct_socket) {
@@ -1274,7 +1278,8 @@ clnt_vc_upcallsdone(struct ct_data *ct)
static void
clnt_vc_dotlsupcall(void *data)
{
- struct ct_data *ct = (struct ct_data *)data;
+ CLIENT *cl = (CLIENT *)data;
+ struct ct_data *ct = (struct ct_data *)cl->cl_private;
enum clnt_stat ret;
uint32_t reterr;
@@ -1311,5 +1316,6 @@ clnt_vc_dotlsupcall(void *data)
ct->ct_rcvstate &= ~RPCRCVSTATE_UPCALLTHREAD;
wakeup(&ct->ct_sslrefno);
mtx_unlock(&ct->ct_lock);
+ CLNT_RELEASE(cl);
kthread_exit();
}