memory leaks

ZIGLIO, Frediano, VF-IT Frediano.Ziglio at vodafone.com
Thu Jan 12 10:09:43 CET 2006


Hi Marcus,
> 
> On Sun, 2006-01-08 at 14:33 +0100, Dirk Stoecker wrote:
> > as promised, I released the memory leak patch for gcrypt on 
> a webpage:
> > 
> > http://www.dstoecker.de/gcrypt.html
> > 
> > It includes the motivation for the patch, the way to 
> download and apply it 
> > as well as compatibility considerations (and a not for 
> usage in dynamic 
> > loading contexts).
> 
> Your website expresses a lot of frustration.  That is understandable,
> but I think we should try to approach this issue 
> constructively.  To do

I think that after some months a people can be a bit frustated :)

> so, we have to solve a complicated technical problem, given certain
> policy constraints.  If we can successfully identify these 
> constraints,
> and potential solutions, we have won a lot.  At least we will better
> understand why certain changes are rejected, and if we can develop a
> long term strategy.
> 
> It is very important that we untangle unrelated issues.  Your patch
> contains different types of changes intermixed.  One thing 
> you can do to
> push forward this issue is to split your patch into several different
> patches so we can address them individually.
> 

I agree, there are changes like configure or syntax (comma after last
enum entry) that are not related to finalization.

> One such issue is finalization.  It seems to me that your 
> code does not
> handle finalization correctly.  Consider the following case: 
> library bar
> and baz both use libgcrypt.  They both hide this fact from the
> application.  The application uses the library specific initializers
> (bar_init and baz_init) which each initialize libgcrypt.  
> Under certain
> conditions this is perfectly legit, in fact, it is the only way
> libgrcypt can be used correctly in such a situation.  Now, imagine baz
> comes with a finalizer, which calls the finalizer for gcrypt 
> you added.
> It seems to me from skimming over your patch that in this 
> case gcrypt is
> deinitialized.  This will potentially break bar's use of gcrypt (I did
> not check if it in fact does so).  It thus seems to me that your
> proposed solution in its current form is at best incomplete, 
> and I don't
> see a trivial fix.
> 

The usual way to fix this issue are mainly two
1- use counter
2- init library at so init

1 is usually preferred (it work even with static library). It consist in
using a counter in initialization. Counter is initially 0 and get
incremented on initialization and decremented on deinit. Initialization
occur only if you call init and counter get to 1

void init()
{
   if (++counter != 1)
     return;
  ... init ...
}

while deinitialization occur if counter get 0

void deinit()
{
  if (--counter != 0)
    return;
  ... deinit ...
}

(I not took into account thread problems)

2 require use of so. Just catch library load and initialize library and
deinit only at library unload. Very difficult to port on Unix systems.

> With regards to the current libgcrypt code, one overriding concern is
> ABI/API compatibility.  Irregardless of what we would _want_ 
> the code to
> look like, the current libgcrypt version is used in dozens of 
> important
> software packages, and making incompatible changes to the 
> ABI/API to the
> _current_ version would need to be carefully justified.  We feel that
> extension of the applicability of the library to new use cases (like
> dlopen'ed plugins) does not justify breaking existing use in dozens of
> software packages.  So any major changes, and my suspicion is that
> cleaning up the allocation issues involves major changes if 
> it is to be
> done right, would have to go into a major revision of the 
> whole package
> including the ABI/API.  This however raises a tail of other questions,
> like how do we carry over the confidence (security wise) that 
> we have in
> the current implementation to the hypothetical major revision, how can
> its development be supported, etc?

Well, current API is just broken for dlopen contexts... let me explain
why. Assume that library A call gcry_set_allocation_handler... now any
time you allocate memory inside libgcrypt you call alloc/free/realloc
provided by library A. Now what happens if library B calls
gcry_set_allocation_handler? Well, I think that all these globals should
be removed (same problem for threadsafe callbacks). 
There are some solution to this problem
- use only static library, any library that will use libgcrypt use a
different libgcrypt library (this break ABI where you provide dynamic
libraries)
- use a single solution (malloc/free/realloc from libc, pthread where
available) and do not use callbacks (ignoring settings), this keep ABI
but you can have some problems mixing calls to gcry_malloc/free/realloc
and "A malloc/free/realloc".
- use a session structure to store callbacks and change all API to
accept this session. This as you can imagine breaks API, however you can
avoid this using a global session and adding new APIs while old one call
new one adding global session, something like

return_type old_function(parameters)
{
   return new_function(global_session, parameters);
}

return_type new_function(session_type session, parameters)
{
   ... do what you want ...
}

you can "implement " old function using macro to keep API but no ABI

gcry_global_session_t gcry_global_session;
#define old_function(a,b,c) new_function(gcry_global_session,a,b,c)

This keep source compatibility.

you can keep ABI providing 2 library: the old one and a new one, on new
one (ie libgcrypting.so in Linux) we have only functions that use
session like

return_type new_function(session_type session, parameters)
{
   ...
}

while old library (that keep old names, ie libgcrypt.so on Linux)

return_type old_function(parameters)
{
   return new_function(global_session, parameters);
}

You can also use a mix of define and libraries so old programs compiled
with new libgcrypt will use new library just adding minimal changes
(define a program session somewhere and call functions in old way)

> 
> Equally important would be to find a convincing story how such a major
> revision could actually look like.  Moritz does have some ideas about
> how to restructure the code to make it more modular and less dependent
> on global statics.  However, some of the core issues are 
> unresolved.  We
> have some ideas, but I don't think we have actually found the best
> solution yet, and I am not sure what the best solution would 
> look like.
> 
> So here is how I suggest we proceed:  If you can identify separate
> issues in your patch, please report them as separate issues, 
> so they can
> be discussed separately.  In particular, I want to understand if your
> finalizer actually correctly solves the problem you identified (see
> above).  Furthermore, I would like to know if you see ways to improve
> the library in its current form without modifying the 
> ABI/API.  Last but
> not least, we can try to envision how an "ideal" libgcrypt would look
> like and see if we can find mechanisms that actually allow to 
> implement
> it.  This list of issues is losely sorted from easy to hard, and from
> high priority to low priority (from my perspective).
> 
> Thanks,
> Marcus
> 

bye
  Frediano Ziglio



More information about the Gcrypt-devel mailing list