- From a95d4fc86dc71e286f0491f5441b713cd03eb07f Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Wed, 26 Aug 2026 15:53:24 +0200
- Subject: [PATCH 2/2] libtirpc: Add |CRITICAL_SECTION| for SSPI operations
- which cannot be used in multiple threads in parallel
- Add |CRITICAL_SECTION| for SSPI operations which cannot be used in multiple
- threads in parallel.
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- libtirpc/src/auth_sspi.c | 83 +++++++++++++++++++++++++++++++---------
- 1 file changed, 65 insertions(+), 18 deletions(-)
- diff --git a/libtirpc/src/auth_sspi.c b/libtirpc/src/auth_sspi.c
- index 1ac1c3a..5dc12b2 100644
- --- a/libtirpc/src/auth_sspi.c
- +++ b/libtirpc/src/auth_sspi.c
- @@ -64,8 +64,23 @@ struct rpc_sspi_data {
- struct rpc_sspi_cred gc; /* client credentials */
- u_int win; /* sequence window */
- TimeStamp expiry;
- +
- + /*
- + * Protect operations on the SSPI context itself. Do not hold this
- + * lock across |clnt_call()|: RPCSEC_GSS context establishment and
- + * destruction recursively enter the AUTH methods through
- + * |clnt_call()|
- + *
- + * Note that the RPC sequence number is allocated atomically, so
- + * callers do not serialize an entire NFS request merely to
- + * obtain a sequence number.
- + */
- + CRITICAL_SECTION sspi_lock;
- };
- +/* |clnt_call()| invokes marshal and wrap on the same worker thread */
- +__declspec(thread) static u_int authsspi_call_seq;
- +
- #define AUTH_PRIVATE(auth) ((struct rpc_sspi_data *)auth->ah_private)
- static struct timeval AUTH_TIMEOUT = { 25, 0 };
- @@ -113,6 +128,13 @@ authsspi_create(CLIENT *clnt, sspi_name_t name, struct rpc_sspi_sec *sec)
- SecInvalidateHandle(&gd->ctx);
- gd->sec = sec;
- +
- + /*
- + * Disable spin count as |&gd->sspi_lock| is typically used
- + * to protect longer-running SSPI API calls
- + */
- + (void)InitializeCriticalSectionAndSpinCount(&gd->sspi_lock, 0);
- +
- gd->gc.gc_v = RPCSEC_SSPI_VERSION;
- gd->gc.gc_proc = RPCSEC_SSPI_INIT;
- gd->gc.gc_svc = gd->sec->svc;
- @@ -206,6 +228,7 @@ authsspi_marshal(AUTH *auth, XDR *xdrs, u_int *seq)
- {
- XDR tmpxdrs;
- char tmp[MAX_AUTH_BYTES];
- + struct opaque_auth cred, verf;
- struct rpc_sspi_data *gd;
- sspi_buffer_desc rpcbuf, checksum;
- uint32_t maj_stat;
- @@ -227,13 +250,13 @@ authsspi_marshal(AUTH *auth, XDR *xdrs, u_int *seq)
- XDR_DESTROY(&tmpxdrs);
- return (FALSE);
- }
- - auth->ah_cred.oa_flavor = RPCSEC_GSS;
- - auth->ah_cred.oa_base = tmp;
- - auth->ah_cred.oa_length = XDR_GETPOS(&tmpxdrs);
- + cred.oa_flavor = RPCSEC_GSS;
- + cred.oa_base = tmp;
- + cred.oa_length = XDR_GETPOS(&tmpxdrs);
- XDR_DESTROY(&tmpxdrs);
- - if (!xdr_opaque_auth(xdrs, &auth->ah_cred)) {
- + if (!xdr_opaque_auth(xdrs, &cred)) {
- log_debug("authsspi_marshal: failed to xdr GSS CRED");
- return (FALSE);
- }
- @@ -251,7 +274,9 @@ authsspi_marshal(AUTH *auth, XDR *xdrs, u_int *seq)
- maj_stat = gss_get_mic(&min_stat, gd->ctx, gd->sec.qop,
- &rpcbuf, &checksum);
- #else
- - maj_stat = sspi_get_mic(&gd->ctx, 0, gd->gc.gc_seq, &rpcbuf, &checksum);
- + EnterCriticalSection(&gd->sspi_lock);
- + maj_stat = sspi_get_mic(&gd->ctx, 0, *seq, &rpcbuf, &checksum);
- + LeaveCriticalSection(&gd->sspi_lock);
- #endif
- if (maj_stat != SEC_E_OK) {
- log_debug("authsspi_marshal: sspi_get_mic failed with %x", maj_stat);
- @@ -261,10 +286,10 @@ authsspi_marshal(AUTH *auth, XDR *xdrs, u_int *seq)
- }
- return (FALSE);
- }
- - auth->ah_verf.oa_flavor = RPCSEC_GSS;
- - auth->ah_verf.oa_base = checksum.value;
- - auth->ah_verf.oa_length = checksum.length;
- - xdr_stat = xdr_opaque_auth(xdrs, &auth->ah_verf);
- + verf.oa_flavor = RPCSEC_GSS;
- + verf.oa_base = checksum.value;
- + verf.oa_length = checksum.length;
- + xdr_stat = xdr_opaque_auth(xdrs, &verf);
- #if 0
- gss_release_buffer(&min_stat, &checksum);
- #else
- @@ -329,7 +354,9 @@ authsspi_validate(AUTH *auth, struct opaque_auth *verf, u_int seq)
- maj_stat = gss_verify_mic(&min_stat, gd->ctx, &signbuf,
- &checksum, &qop_state);
- #else
- - maj_stat = sspi_verify_mic(&gd->ctx, cur_seq, &signbuf, &checksum, &qop_state);
- + EnterCriticalSection(&gd->sspi_lock);
- + maj_stat = sspi_verify_mic(&gd->ctx, cur_seq, &signbuf, &checksum, &qop_state);
- + LeaveCriticalSection(&gd->sspi_lock);
- #endif
- if (maj_stat != SEC_E_OK) {
- log_debug("authsspi_validate: VerifySignature failed with %x", maj_stat);
- @@ -415,6 +442,7 @@ authsspi_refresh(AUTH *auth, void *tmp)
- wtkn[0].pvBuffer = send_token.value;
- log_debug("calling InitializeSecurityContextA for %s", gd->name);
- + EnterCriticalSection(&gd->sspi_lock);
- maj_stat = InitializeSecurityContextA(
- &gd->sec->cred,
- ((i==0)?NULL:&gd->ctx),
- @@ -428,6 +456,7 @@ authsspi_refresh(AUTH *auth, void *tmp)
- &out_desc,
- &ret_flags,
- &gd->expiry);
- + LeaveCriticalSection(&gd->sspi_lock);
- #endif
- if (recv_tokenp != SSPI_C_NO_BUFFER) {
- #if 0
- @@ -509,7 +538,10 @@ authsspi_refresh(AUTH *auth, void *tmp)
- maj_stat = gss_verify_mic(&min_stat, gd->ctx,
- &bufin, &bufout, &qop_state);
- #else
- - maj_stat = sspi_verify_mic(&gd->ctx, 0, &bufin, &gd->gc_wire_verf, &qop_state);
- + EnterCriticalSection(&gd->sspi_lock);
- + maj_stat = sspi_verify_mic(&gd->ctx, 0, &bufin,
- + &gd->gc_wire_verf, &qop_state);
- + LeaveCriticalSection(&gd->sspi_lock);
- #endif
- if (maj_stat != SEC_E_OK) {
- log_debug("authgss_refresh: sspi_verify_mic failed with %x", maj_stat);
- @@ -577,7 +609,9 @@ authsspi_destroy_context(AUTH *auth)
- gd->gc.gc_proc = RPCSEC_SSPI_DESTROY;
- clnt_call(gd->clnt, NULLPROC, (xdrproc_t)xdr_void, NULL,
- (xdrproc_t)xdr_void, NULL, AUTH_TIMEOUT);
- - DeleteSecurityContext(&gd->ctx);
- + EnterCriticalSection(&gd->sspi_lock);
- + DeleteSecurityContext(&gd->ctx);
- + LeaveCriticalSection(&gd->sspi_lock);
- }
- sspi_release_buffer(&gd->gc.gc_ctx);
- SecInvalidateHandle(&gd->ctx);
- @@ -616,6 +650,7 @@ authsspi_destroy(AUTH *auth)
- free(gd->name);
- #endif
- FreeCredentialsHandle(&gd->sec->cred);
- + DeleteCriticalSection(&gd->sspi_lock);
- free(gd->sec);
- free(gd);
- free(auth);
- @@ -633,9 +668,15 @@ authsspi_wrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr)
- if (!gd->established || gd->sec->svc == RPCSEC_SSPI_SVC_NONE) {
- return ((*xdr_func)(xdrs, xdr_ptr));
- }
- - return (xdr_rpc_sspi_data(xdrs, xdr_func, xdr_ptr,
- - &gd->ctx, gd->sec->qop,
- - gd->sec->svc, gd->gc.gc_seq));
- +
- + bool_t result;
- + EnterCriticalSection(&gd->sspi_lock);
- + result = xdr_rpc_sspi_data(xdrs, xdr_func, xdr_ptr,
- + &gd->ctx, gd->sec->qop,
- + gd->sec->svc, authsspi_call_seq);
- + LeaveCriticalSection(&gd->sspi_lock);
- +
- + return result;
- }
- bool_t
- @@ -650,9 +691,15 @@ authsspi_unwrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, u_in
- if (!gd->established || gd->sec->svc == RPCSEC_SSPI_SVC_NONE) {
- return ((*xdr_func)(xdrs, xdr_ptr));
- }
- - return (xdr_rpc_sspi_data(xdrs, xdr_func, xdr_ptr,
- - &gd->ctx, gd->sec->qop,
- - gd->sec->svc, seq));
- +
- + bool_t result;
- + EnterCriticalSection(&gd->sspi_lock);
- + result = xdr_rpc_sspi_data(xdrs, xdr_func, xdr_ptr,
- + &gd->ctx, gd->sec->qop,
- + gd->sec->svc, seq);
- + LeaveCriticalSection(&gd->sspi_lock);
- +
- + return result;
- }
- uint32_t sspi_get_mic(void *arg_ctx, u_int qop, u_int seq,
- --
- 2.51.0
0002-libtirpc-Add-CRITICAL_SECTION-for-SSPI-operations-wh.patch
Posted by Anonymous on Wed 26th Aug 2026 17:07
raw | new post
Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.
nrubsig.kpaste.net RSS