[gnutls-dev] Re: living without global variables
ZIGLIO, Frediano, VF-IT
Frediano.Ziglio at vodafone.com
Tue Jan 3 14:36:26 CET 2006
>
> > Doesn't it? gnutls' global init function does _something_ with
> > Libgcrypt. How is that different?
>
> Gnutls handles the Libgcrypt initialization internally and thus
> requires that the user of gnutls has knowledge about the internal use
> of libgcrypt. If you are using libgcrypt in a threading environment
> the gnutls callers needs to make sure that Libgcrypt has been
> initialized correctly - the last time I checked, gnutls does not know
> the threading system in use and thus can't initialize
> Libgcrypt properly.
>
> With an initialization function similar to the one of Libgcrypt it
> would be possible to hide the use of Libgcrypt.
>
> We do not create thread specific versions of Libgcrypt because this
> would require all libs using Libgcrypt to also come in different
> flavors (plain, pthread, pth) - not very efficient. For certain OSes
> we might be able to do some trickery in detecting and initializing the
> threading lib in use but this is not portable.
>
> > Assuming you have to have global variables, of course.
>
> The major reason for global state is the entropy pool. Collecting
> entropy is a time consuming task and we can't do it for each new
> session. Another one is libgcrypt's "secure" memory allocation
> functions - obviously this can't be done on a per session base or
> delegated to a daemon. With encrypted swap you won't need it, but
> this OS feature is not yet in widespread use.
>
> Thus this is all a matter of telling libgcrypt to use the correct
> threading system.
>
> Unloading Libgcrypt is not possible unless all users agree on shutting
> down all threads (but one) using Libgcrypt, restoring all hooks and
> releasing all secure memory. Libgcrypt can't detect such a condition
> and this is the reason we don't provide a deinit function.
>
> For a plugin system one could use wrapper functions to provide a
> managed interface to libgcrypt. The problem is that you need to do
> this for most libraries which are subject to "unloading" and change
> all those libraries to use these wrapper functions. Writing a plugin
> system in a portable way is not easy. Frankly, I see no way to create
> in-process plugins without restricting the APIs a plugin may use.
> Creating plugins as separate processes is far easier, more secure and
> really portable.
>
>
> Shalom-Salam,
>
> Werner
>
There is also another possibility that can fix (I hope) all problems.
Mainly initializers in libgcrypt are functions that manage module
registrations. Module registrations just add entries to some linked
list. It would be possible to initialize these lists statically. Well,
let me explain with an example this solution. gcry_module is defined as
struct gcry_module
{
struct gcry_module *next; /* List pointers. */
struct gcry_module **prevp;
void *spec; /* The acctual specs. */
int flags; /* Associated flags. */
int counter; /* Use counter. */
unsigned int mod_id; /* ID of this module. */
};
we could define a statically handled list as
extern gcry_module _gcry_module1;
extern gcry_module _gcry_module2;
static gcry_module_t ciphers_registered = &_gcry_module1;
gcry_module _gcry_module1 = {
&_gcry_module2,
&ciphers_registered,
my_cipher_spec1, /* replace with correct value*/
FLAG_MODULE_STATIC_ALLOCATED, /* or whatever you decide */
0, /* ?? */
MODULE_ID_MIN
};
gcry_module _gcry_module2 = {
NULL,
&_gcry_module1.next,
my_cipher_spec2,
FLAG_MODULE_STATIC_ALLOCATED,
0, /* ?? */
MODULE_ID_MIN+1
};
This method use a static allocation (and in this case even a static
initialization but this can be changed as you like). Someone could
object that if a shared library adds some module dynamically to gcrypt
in this case we would still have a memory leak however is up to shared
library that register the module to release it.
Frediano Ziglio
More information about the Gcrypt-devel
mailing list