From 5c797a24a7d6337b5e654079a8d815199b1e8364 Mon Sep 17 00:00:00 2001 From: Carmelo Amoroso Date: Thu, 2 Feb 2012 18:22:36 +0100 Subject: [PATCH] inet:rpc: fix authnone_marshal in multithreading context This is a port of glibc's fix by Zack Weinberg as reported in http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=142312, and discussed in http://sourceware.org/ml/libc-alpha/2002-04/msg00069.html and following. Signed-off-by: Carmelo Amoroso --- libc/inet/rpc/auth_none.c | 59 +++++++++++++++++++++---------------------- libc/inet/rpc/rpc_private.h | 2 -- libc/inet/rpc/rpc_thread.c | 1 - 3 files changed, 29 insertions(+), 33 deletions(-) diff --git a/libc/inet/rpc/auth_none.c b/libc/inet/rpc/auth_none.c index c48bbfe..d066f6b 100644 --- a/libc/inet/rpc/auth_none.c +++ b/libc/inet/rpc/auth_none.c @@ -66,49 +66,48 @@ struct authnone_private_s { char marshalled_client[MAX_MARSHAL_SIZE]; u_int mcnt; }; -#ifdef __UCLIBC_HAS_THREADS__ -#define authnone_private (*(struct authnone_private_s **)&RPC_THREAD_VARIABLE(authnone_private_s)) -#else -static struct authnone_private_s *authnone_private; -#endif -AUTH * -authnone_create (void) +static struct authnone_private_s authnone_private; +__libc_once_define(static, authnone_private_guard); + +static void authnone_create_once (void); + +static void +authnone_create_once (void) { struct authnone_private_s *ap; XDR xdr_stream; XDR *xdrs; - ap = (struct authnone_private_s *) authnone_private; - if (ap == NULL) - { - ap = (struct authnone_private_s *) calloc (1, sizeof (*ap)); - if (ap == NULL) - return NULL; - authnone_private = ap; - } - if (!ap->mcnt) - { - ap->no_client.ah_cred = ap->no_client.ah_verf = _null_auth; - ap->no_client.ah_ops = (struct auth_ops *)&ops; - xdrs = &xdr_stream; - xdrmem_create (xdrs, ap->marshalled_client, (u_int) MAX_MARSHAL_SIZE, - XDR_ENCODE); - (void) xdr_opaque_auth (xdrs, &ap->no_client.ah_cred); - (void) xdr_opaque_auth (xdrs, &ap->no_client.ah_verf); - ap->mcnt = XDR_GETPOS (xdrs); - XDR_DESTROY (xdrs); - } - return (&ap->no_client); + ap = &authnone_private; + + ap->no_client.ah_cred = ap->no_client.ah_verf = _null_auth; + ap->no_client.ah_ops = (struct auth_ops *) &ops; + xdrs = &xdr_stream; + xdrmem_create(xdrs, ap->marshalled_client, + (u_int) MAX_MARSHAL_SIZE, XDR_ENCODE); + (void) xdr_opaque_auth(xdrs, &ap->no_client.ah_cred); + (void) xdr_opaque_auth(xdrs, &ap->no_client.ah_verf); + ap->mcnt = XDR_GETPOS (xdrs); + XDR_DESTROY (xdrs); +} + +AUTH * +authnone_create (void) +{ + __libc_once (authnone_private_guard, authnone_create_once); + return &authnone_private.no_client; } libc_hidden_def(authnone_create) static bool_t -authnone_marshal (AUTH *client attribute_unused, XDR *xdrs) +authnone_marshal (AUTH *client, XDR *xdrs) { struct authnone_private_s *ap; - ap = authnone_private; + /* authnone_create returned authnone_private->no_client, which is + the first field of struct authnone_private_s. */ + ap = (struct authnone_private_s *) client; if (ap == NULL) return FALSE; return (*xdrs->x_ops->x_putbytes) (xdrs, ap->marshalled_client, ap->mcnt); diff --git a/libc/inet/rpc/rpc_private.h b/libc/inet/rpc/rpc_private.h index ede3ddf..e1214d2 100644 --- a/libc/inet/rpc/rpc_private.h +++ b/libc/inet/rpc/rpc_private.h @@ -18,8 +18,6 @@ struct rpc_thread_variables { struct pollfd *svc_pollfd_s; /* Global, rpc_common.c */ int svc_max_pollfd_s; /* Global, rpc_common.c */ - void *authnone_private_s; /* auth_none.c */ - void *clnt_perr_buf_s; /* clnt_perr.c */ void *clntraw_private_s; /* clnt_raw.c */ diff --git a/libc/inet/rpc/rpc_thread.c b/libc/inet/rpc/rpc_thread.c index 71303b2..3367659 100644 --- a/libc/inet/rpc/rpc_thread.c +++ b/libc/inet/rpc/rpc_thread.c @@ -32,7 +32,6 @@ __rpc_thread_destroy (void) __rpc_thread_svc_cleanup (); __rpc_thread_clnt_cleanup (); /*__rpc_thread_key_cleanup (); */ - free (tvp->authnone_private_s); free (tvp->clnt_perr_buf_s); free (tvp->clntraw_private_s); free (tvp->svcraw_private_s); -- 1.7.10.4