Orivej Desh wrote on Tue, 23 May 2017 08:20 +0000:
> Hello,
> 
> I noticed in dmesg that in my repository svnserve occasionally crashes.
> This happens at exit, so it is not visible to end users.  I captured a
> few sessions at the svn protocol level that resulted in a crash; client
> commands are quite different in each one; sending an input that crashed
> `svnserve -t` again always crashes it; I did not manage to reproduce
> this in a new repository.  I tested with subversion 1.9.0, 1.9.4 and
> subversion trunk, apr 1.3.0 and apr 1.5.2 with the same result.
> 

I cannot reproduce this with apr 1.5.1-3 (debian), svn 1.9.4 (self compiled),
and clang 3.5, under 'make svnserveautocheck'.  I use 1.9.4 because that's the
traceback you posted; let's do further analysis on trunk if the problem
reproduces there.

> Here is the AddressSanitizer report of the problem (with subversion
> 1.9.4 and apr 1.3.0).  For me it seems that a piece of memory belonging
> to the object_pool is registered for run_cleanups in the main pool, then
> right before return from main() all child pools of the main pool are
> destroyed, then run_cleanups of the main pool calls object_ref_cleanup
> with a pointer to a freed memory.  Is this correct?  How is this
> supposed to work?  Could you help me spot the difference between
> expected and unexpected paths of code concerning the issue?
> 

The report says that the use-after-free occured inside the cleanup handler.  It
doesn't say where the accessed object was allocated or freed; to get that info,
you'd have had to compile APR with pool debugging (--enable-pool-debug), then
the second and third traceback would have pointed to the site of the malloc()
and of the apr_pool_clear().

Cleanup handlers work as follows: «apr_pool_cleanup_register(pool, baton, f, g)»
calls «f(baton)» when POOL is cleared.  If BATON had been free()d before POOL
is cleared, then F will access freed memory.  

Therefore, there are a few options to fixing such issues. One could install the
cleanup handler F on a different pool, or duplicate the BATON object into a
different pool, handler is invoked), or sometimes to use 
apr_pool_pre_cleanup_register()
instead.  I'm not sure which of these options is best in this case (not
familiar with this module).

The pool cleanup is registered in add_object_ref().  Can you break in that
function and confirm which of its two callsites is involved?

Thanks for the report!

Daniel

Reply via email to