pastebin - collaborative debugging tool
nrubsig.kpaste.net RSS


0002-libtirpc-Add-CRITICAL_SECTION-for-SSPI-operations-wh.patch
Posted by Anonymous on Wed 26th Aug 2026 17:07
raw | new post

  1. From a95d4fc86dc71e286f0491f5441b713cd03eb07f Mon Sep 17 00:00:00 2001
  2. From: Roland Mainz <roland.mainz@nrubsig.org>
  3. Date: Wed, 26 Aug 2026 15:53:24 +0200
  4. Subject: [PATCH 2/2] libtirpc: Add |CRITICAL_SECTION| for SSPI operations
  5.  which cannot be used in multiple threads in parallel
  6.  
  7. Add |CRITICAL_SECTION| for SSPI operations which cannot be used in multiple
  8. threads in parallel.
  9.  
  10. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  11. ---
  12. libtirpc/src/auth_sspi.c | 83 +++++++++++++++++++++++++++++++---------
  13.  1 file changed, 65 insertions(+), 18 deletions(-)
  14.  
  15. diff --git a/libtirpc/src/auth_sspi.c b/libtirpc/src/auth_sspi.c
  16. index 1ac1c3a..5dc12b2 100644
  17. --- a/libtirpc/src/auth_sspi.c
  18. +++ b/libtirpc/src/auth_sspi.c
  19. @@ -64,8 +64,23 @@ struct rpc_sspi_data {
  20.         struct rpc_sspi_cred gc;                    /* client credentials */
  21.         u_int               win;                    /* sequence window */
  22.      TimeStamp           expiry;
  23. +
  24. +    /*
  25. +     * Protect operations on the SSPI context itself. Do not hold this
  26. +     * lock across |clnt_call()|: RPCSEC_GSS context establishment and
  27. +     * destruction recursively enter the AUTH methods through
  28. +     * |clnt_call()|
  29. +     *
  30. +     * Note that the RPC sequence number is allocated atomically, so
  31. +     * callers do not serialize an entire NFS request merely to
  32. +     * obtain a sequence number.
  33. +     */
  34. +    CRITICAL_SECTION    sspi_lock;
  35.  };
  36.  
  37. +/* |clnt_call()| invokes marshal and wrap on the same worker thread */
  38. +__declspec(thread) static u_int authsspi_call_seq;
  39. +
  40.  #define        AUTH_PRIVATE(auth)      ((struct rpc_sspi_data *)auth->ah_private)
  41.  
  42.  static struct timeval AUTH_TIMEOUT = { 25, 0 };
  43. @@ -113,6 +128,13 @@ authsspi_create(CLIENT *clnt, sspi_name_t name, struct rpc_sspi_sec *sec)
  44.         SecInvalidateHandle(&gd->ctx);
  45.         gd->sec = sec;
  46.  
  47. +
  48. +       /*
  49. +        * Disable spin count as |&gd->sspi_lock| is typically used
  50. +        * to protect longer-running SSPI API calls
  51. +        */
  52. +       (void)InitializeCriticalSectionAndSpinCount(&gd->sspi_lock, 0);
  53. +
  54.         gd->gc.gc_v = RPCSEC_SSPI_VERSION;
  55.         gd->gc.gc_proc = RPCSEC_SSPI_INIT;
  56.         gd->gc.gc_svc = gd->sec->svc;
  57. @@ -206,6 +228,7 @@ authsspi_marshal(AUTH *auth, XDR *xdrs, u_int *seq)
  58.  {
  59.         XDR tmpxdrs;
  60.         char tmp[MAX_AUTH_BYTES];
  61. +       struct opaque_auth cred, verf;
  62.         struct rpc_sspi_data *gd;
  63.         sspi_buffer_desc rpcbuf, checksum;
  64.         uint32_t maj_stat;
  65. @@ -227,13 +250,13 @@ authsspi_marshal(AUTH *auth, XDR *xdrs, u_int *seq)
  66.                 XDR_DESTROY(&tmpxdrs);
  67.                 return (FALSE);
  68.         }
  69. -       auth->ah_cred.oa_flavor = RPCSEC_GSS;
  70. -       auth->ah_cred.oa_base = tmp;
  71. -       auth->ah_cred.oa_length = XDR_GETPOS(&tmpxdrs);
  72. +       cred.oa_flavor = RPCSEC_GSS;
  73. +       cred.oa_base = tmp;
  74. +       cred.oa_length = XDR_GETPOS(&tmpxdrs);
  75.  
  76.         XDR_DESTROY(&tmpxdrs);
  77.  
  78. -       if (!xdr_opaque_auth(xdrs, &auth->ah_cred)) {
  79. +       if (!xdr_opaque_auth(xdrs, &cred)) {
  80.          log_debug("authsspi_marshal: failed to xdr GSS CRED");
  81.                 return (FALSE);
  82.      }
  83. @@ -251,7 +274,9 @@ authsspi_marshal(AUTH *auth, XDR *xdrs, u_int *seq)
  84.         maj_stat = gss_get_mic(&min_stat, gd->ctx, gd->sec.qop,
  85.                             &rpcbuf, &checksum);
  86.  #else
  87. -    maj_stat = sspi_get_mic(&gd->ctx, 0, gd->gc.gc_seq, &rpcbuf, &checksum);
  88. +       EnterCriticalSection(&gd->sspi_lock);
  89. +       maj_stat = sspi_get_mic(&gd->ctx, 0, *seq, &rpcbuf, &checksum);
  90. +       LeaveCriticalSection(&gd->sspi_lock);
  91.  #endif
  92.         if (maj_stat != SEC_E_OK) {
  93.                 log_debug("authsspi_marshal: sspi_get_mic failed with %x", maj_stat);
  94. @@ -261,10 +286,10 @@ authsspi_marshal(AUTH *auth, XDR *xdrs, u_int *seq)
  95.                 }
  96.                 return (FALSE);
  97.         }
  98. -       auth->ah_verf.oa_flavor = RPCSEC_GSS;
  99. -       auth->ah_verf.oa_base = checksum.value;
  100. -       auth->ah_verf.oa_length = checksum.length;
  101. -       xdr_stat = xdr_opaque_auth(xdrs, &auth->ah_verf);
  102. +       verf.oa_flavor = RPCSEC_GSS;
  103. +       verf.oa_base = checksum.value;
  104. +       verf.oa_length = checksum.length;
  105. +       xdr_stat = xdr_opaque_auth(xdrs, &verf);
  106.  #if 0
  107.         gss_release_buffer(&min_stat, &checksum);
  108.  #else
  109. @@ -329,7 +354,9 @@ authsspi_validate(AUTH *auth, struct opaque_auth *verf, u_int seq)
  110.         maj_stat = gss_verify_mic(&min_stat, gd->ctx, &signbuf,
  111.                                   &checksum, &qop_state);
  112.  #else
  113. -    maj_stat = sspi_verify_mic(&gd->ctx, cur_seq, &signbuf, &checksum, &qop_state);
  114. +       EnterCriticalSection(&gd->sspi_lock);
  115. +       maj_stat = sspi_verify_mic(&gd->ctx, cur_seq, &signbuf, &checksum, &qop_state);
  116. +       LeaveCriticalSection(&gd->sspi_lock);
  117.  #endif
  118.         if (maj_stat != SEC_E_OK) {
  119.                 log_debug("authsspi_validate: VerifySignature failed with %x", maj_stat);
  120. @@ -415,6 +442,7 @@ authsspi_refresh(AUTH *auth, void *tmp)
  121.          wtkn[0].pvBuffer = send_token.value;
  122.          log_debug("calling InitializeSecurityContextA for %s", gd->name);
  123.  
  124. +       EnterCriticalSection(&gd->sspi_lock);
  125.          maj_stat = InitializeSecurityContextA(
  126.                          &gd->sec->cred,
  127.                          ((i==0)?NULL:&gd->ctx),
  128. @@ -428,6 +456,7 @@ authsspi_refresh(AUTH *auth, void *tmp)
  129.                          &out_desc,
  130.                          &ret_flags,
  131.                          &gd->expiry);
  132. +       LeaveCriticalSection(&gd->sspi_lock);
  133.  #endif
  134.                 if (recv_tokenp != SSPI_C_NO_BUFFER) {
  135.  #if 0
  136. @@ -509,7 +538,10 @@ authsspi_refresh(AUTH *auth, void *tmp)
  137.                         maj_stat = gss_verify_mic(&min_stat, gd->ctx,
  138.                                 &bufin, &bufout, &qop_state);
  139.  #else
  140. -            maj_stat = sspi_verify_mic(&gd->ctx, 0, &bufin, &gd->gc_wire_verf, &qop_state);
  141. +                       EnterCriticalSection(&gd->sspi_lock);
  142. +                       maj_stat = sspi_verify_mic(&gd->ctx, 0, &bufin,
  143. +                               &gd->gc_wire_verf, &qop_state);
  144. +                       LeaveCriticalSection(&gd->sspi_lock);
  145.  #endif
  146.                         if (maj_stat != SEC_E_OK) {
  147.                                 log_debug("authgss_refresh: sspi_verify_mic failed with %x", maj_stat);
  148. @@ -577,7 +609,9 @@ authsspi_destroy_context(AUTH *auth)
  149.                         gd->gc.gc_proc = RPCSEC_SSPI_DESTROY;
  150.                         clnt_call(gd->clnt, NULLPROC, (xdrproc_t)xdr_void, NULL,
  151.                                   (xdrproc_t)xdr_void, NULL, AUTH_TIMEOUT);
  152. -            DeleteSecurityContext(&gd->ctx);
  153. +                       EnterCriticalSection(&gd->sspi_lock);
  154. +                       DeleteSecurityContext(&gd->ctx);
  155. +                       LeaveCriticalSection(&gd->sspi_lock);
  156.                 }
  157.          sspi_release_buffer(&gd->gc.gc_ctx);
  158.          SecInvalidateHandle(&gd->ctx);
  159. @@ -616,6 +650,7 @@ authsspi_destroy(AUTH *auth)
  160.      free(gd->name);
  161.  #endif
  162.      FreeCredentialsHandle(&gd->sec->cred);
  163. +    DeleteCriticalSection(&gd->sspi_lock);
  164.      free(gd->sec);
  165.         free(gd);
  166.         free(auth);
  167. @@ -633,9 +668,15 @@ authsspi_wrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr)
  168.         if (!gd->established || gd->sec->svc == RPCSEC_SSPI_SVC_NONE) {
  169.                 return ((*xdr_func)(xdrs, xdr_ptr));
  170.         }
  171. -       return (xdr_rpc_sspi_data(xdrs, xdr_func, xdr_ptr,
  172. -                                &gd->ctx, gd->sec->qop,
  173. -                                gd->sec->svc, gd->gc.gc_seq));
  174. +
  175. +       bool_t result;
  176. +       EnterCriticalSection(&gd->sspi_lock);
  177. +       result = xdr_rpc_sspi_data(xdrs, xdr_func, xdr_ptr,
  178. +               &gd->ctx, gd->sec->qop,
  179. +               gd->sec->svc, authsspi_call_seq);
  180. +       LeaveCriticalSection(&gd->sspi_lock);
  181. +
  182. +       return result;
  183.  }
  184.  
  185.  bool_t
  186. @@ -650,9 +691,15 @@ authsspi_unwrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, u_in
  187.         if (!gd->established || gd->sec->svc == RPCSEC_SSPI_SVC_NONE) {
  188.                 return ((*xdr_func)(xdrs, xdr_ptr));
  189.         }
  190. -       return (xdr_rpc_sspi_data(xdrs, xdr_func, xdr_ptr,
  191. -                                &gd->ctx, gd->sec->qop,
  192. -                                gd->sec->svc, seq));
  193. +
  194. +       bool_t result;
  195. +       EnterCriticalSection(&gd->sspi_lock);
  196. +       result = xdr_rpc_sspi_data(xdrs, xdr_func, xdr_ptr,
  197. +               &gd->ctx, gd->sec->qop,
  198. +               gd->sec->svc, seq);
  199. +       LeaveCriticalSection(&gd->sspi_lock);
  200. +
  201. +       return result;
  202.  }
  203.  
  204.  uint32_t sspi_get_mic(void *arg_ctx, u_int qop, u_int seq,
  205. --
  206. 2.51.0

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.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at