I could reproduce this bug on wheezy environment (x86_64-linux-gnu).

I got the backtrace.  It was indeed 'malloc' interrupted by
signal, and signal_handler called 'free'.

Attached is a fix.  It works for me.

(gdb) bt
#0  0x00007fb7c9aab4cb in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#1  0x00007fb7c9a416b8 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#2  0x00007fb7c9a3faa1 in free () from /lib/x86_64-linux-gnu/libc.so.6
#3  0x00000000004a6e7b in dotlock_destroy_unix (h=0x2274080) at 
../../util/dotlock.c:890
#4  dotlock_destroy (h=0x2274080) at ../../util/dotlock.c:941
#5  0x00000000004a6ed8 in dotlock_remove_lockfiles () at 
../../util/dotlock.c:1304
#6  0x000000000042f8ae in got_fatal_signal (sig=1) at ../../g10/signal.c:125
#7  <signal handler called>
#8  0x00007fb7c9a3d348 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#9  0x00007fb7c9a3fb90 in malloc () from /lib/x86_64-linux-gnu/libc.so.6
#10 0x00000000004a2688 in xmalloc (n=n@entry=256) at ../../util/memory.c:443
#11 0x000000000049c25a in mpi_alloc_limb_space (nlimbs=nlimbs@entry=32, 
secure=<optimized out>) at ../../mpi/mpiutil.c:146
#12 0x000000000049c0e2 in mpihelp_mul_karatsuba_case (prodp=0x2499470, 
up=0x2467420, usize=16, vp=0x2467420, vsize=vsize@entry=16, 
ctx=ctx@entry=0x7fff618a97f0) at ../../mpi/mpih-mul.c:388
#13 0x000000000049bd92 in mpihelp_mul (prodp=prodp@entry=0x2499470, 
up=up@entry=0x2467420, usize=usize@entry=16, vp=vp@entry=0x2467420, 
vsize=vsize@entry=16) at ../../mpi/mpih-mul.c:522
#14 0x00000000004986ea in mpi_mul (w=0x246c280, u=<optimized out>, v=<optimized 
out>) at ../../mpi/mpi-mul.c:187
#15 0x00000000004988b9 in mpi_mulm (w=0x246c280, u=<optimized out>, 
v=<optimized out>, m=0x23a2340) at ../../mpi/mpi-mul.c:211
#16 0x0000000000499568 in mpi_mulpowm (res=0x246c140, basearray=0x7fff618a99a0, 
exparray=<optimized out>, m=0x23a2340) at ../../mpi/mpi-mpow.c:71
#17 0x000000000048b703 in verify (pkey=0x7fff618a9a20, hash=0x23b6110, 
s=0x25081c0, r=0x2508130) at ../../cipher/dsa.c:349
#18 verify (r=0x2508130, s=0x25081c0, hash=0x23b6110, pkey=0x7fff618a9a20) at 
../../cipher/dsa.c:318
#19 0x000000000048c0e0 in dsa_verify (algo=<optimized out>, hash=<optimized 
out>, data=<optimized out>, pkey=<optimized out>) at ../../cipher/dsa.c:457
#20 0x000000000042a9fb in do_check (ret_pk=0x0, digest=0x227d7f0, 
sig=0x2508050, pk=0x244d230, r_expired=<optimized out>, r_revoked=<optimized 
out>) at ../../g10/sig-check.c:293
#21 do_check (pk=0x244d230, sig=0x2508050, digest=0x227d7f0, 
r_expired=<optimized out>, r_revoked=<optimized out>, ret_pk=0x0) at 
../../g10/sig-check.c:237
#22 0x000000000042b705 in check_key_signature2 (root=root@entry=0x24b2350, 
node=node@entry=0x2456cb0, check_pk=check_pk@entry=0x0, 
ret_pk=ret_pk@entry=0x0, is_selfsig=is_selfsig@entry=0x0, 
r_expiredate=r_expiredate@entry=0x0, r_expired=r_expired@entry=0x0) at 
../../g10/sig-check.c:640
#23 0x000000000042b97b in check_key_signature (root=root@entry=0x24b2350, 
node=node@entry=0x2456cb0, is_selfsig=is_selfsig@entry=0x0) at 
../../g10/sig-check.c:499
#24 0x0000000000410531 in merge_selfsigs_main (rinfo=0x7fff618a9bd0, 
r_revoked=<synthetic pointer>, keyblock=<optimized out>) at 
../../g10/getkey.c:1838
#25 merge_selfsigs (keyblock=<optimized out>) at ../../g10/getkey.c:2319
#26 merge_selfsigs (keyblock=<optimized out>) at ../../g10/getkey.c:2298
#27 0x00000000004138fc in merge_keys_and_selfsig (keyblock=<optimized out>) at 
../../g10/getkey.c:1385
#28 0x000000000042f0a2 in list_all (secret=secret@entry=0) at 
../../g10/keylist.c:446
#29 0x000000000042f5cb in public_key_list (list=0x0) at ../../g10/keylist.c:107
#30 0x0000000000408f5c in main (argc=0, argv=0x7fff618aa288) at 
../../g10/gpg.c:3633
-- 

diff --git a/g10/gpgv.c b/g10/gpgv.c
index 9ee8032..2d51829 100644
--- a/g10/gpgv.c
+++ b/g10/gpgv.c
@@ -434,7 +434,7 @@ void rl_free_line_state (void) {}
 void dotlock_disable(void) {}
 dotlock_t dotlock_create (const char *file_to_lock, unsigned int flags)
 { return NULL; }
-void dotlock_destroy (dotlock_t h) {}
+void dotlock_destroy (dotlock_t h, int reclaim) {}
 int dotlock_take (dotlock_t h, long timeout) { return 0;}
 int dotlock_release (dotlock_t h) {return 0;}
-void dotlock_remove_lockfiles (void) {}
+void dotlock_remove_lockfiles (void, int reclaim) {}
diff --git a/g10/keydb.c b/g10/keydb.c
index d6d83e2..8be1945 100644
--- a/g10/keydb.c
+++ b/g10/keydb.c
@@ -181,7 +181,7 @@ maybe_create_keyring (char *filename, int force)
   if (lockhd)
     {
       dotlock_release (lockhd);
-      dotlock_destroy (lockhd);
+      dotlock_destroy (lockhd, 1);
     }
   return rc;
 }
diff --git a/g10/signal.c b/g10/signal.c
index 086bf51..44b863d 100644
--- a/g10/signal.c
+++ b/g10/signal.c
@@ -122,7 +122,7 @@ got_fatal_signal( int sig )
 
     /* Reset action to default action and raise signal again. */
     init_one_signal (sig, SIG_DFL, 0);
-    dotlock_remove_lockfiles ();
+    dotlock_remove_lockfiles (0);
 #ifdef __riscos__
     riscos_close_fds ();
 #endif /* __riscos__ */
diff --git a/include/dotlock.h b/include/dotlock.h
index 920a81a..0453792 100644
--- a/include/dotlock.h
+++ b/include/dotlock.h
@@ -101,10 +101,11 @@ void dotlock_disable (void);
 dotlock_t dotlock_create (const char *file_to_lock, unsigned int flags);
 void dotlock_set_fd (dotlock_t h, int fd);
 int  dotlock_get_fd (dotlock_t h);
-void dotlock_destroy (dotlock_t h);
+void dotlock_destroy (dotlock_t h, int reclaim);
 int dotlock_take (dotlock_t h, long timeout);
 int dotlock_release (dotlock_t h);
-void dotlock_remove_lockfiles (void);
+void dotlock_remove_lockfiles (int reclaim);
+void dotlock_remove_lockfiles_reclaim (void);
 
 #ifdef __cplusplus
 }
diff --git a/util/dotlock.c b/util/dotlock.c
index c5f3a78..27c2bb2 100644
--- a/util/dotlock.c
+++ b/util/dotlock.c
@@ -128,7 +128,7 @@
    unlinked using the atexit handler.  If you don't need the lock file
    anymore, you may also explicitly remove it with a call to:
 
-     dotlock_destroy (h);
+     dotlock_destroy (h, 1);
 
    To actually lock the file, you use:
 
@@ -823,7 +823,7 @@ dotlock_create (const char *file_to_lock, unsigned int flags)
 
   if ( !initialized )
     {
-      atexit (dotlock_remove_lockfiles);
+      atexit (dotlock_remove_lockfiles_reclaim);
       initialized = 1;
     }
 
@@ -881,13 +881,14 @@ dotlock_get_fd (dotlock_t h)
 #ifdef HAVE_POSIX_SYSTEM
 /* Unix specific code of destroy_dotlock.  */
 static void
-dotlock_destroy_unix (dotlock_t h)
+dotlock_destroy_unix (dotlock_t h, int reclaim)
 {
   if (h->locked && h->lockname)
     unlink (h->lockname);
   if (h->tname && !h->use_o_excl)
     unlink (h->tname);
-  jnlib_free (h->tname);
+  if (reclaim)
+    jnlib_free (h->tname);
 }
 #endif /*HAVE_POSIX_SYSTEM*/
 
@@ -911,7 +912,7 @@ dotlock_destroy_w32 (dotlock_t h)
 
 /* Destroy the locck handle H and release the lock.  */
 void
-dotlock_destroy (dotlock_t h)
+dotlock_destroy (dotlock_t h, int reclaim)
 {
   dotlock_t hprev, htmp;
 
@@ -938,11 +939,13 @@ dotlock_destroy (dotlock_t h)
 #ifdef HAVE_DOSISH_SYSTEM
       dotlock_destroy_w32 (h);
 #else /* !HAVE_DOSISH_SYSTEM */
-      dotlock_destroy_unix (h);
+      dotlock_destroy_unix (h, reclaim);
 #endif /* HAVE_DOSISH_SYSTEM */
-      jnlib_free (h->lockname);
+      if (reclaim)
+	jnlib_free (h->lockname);
     }
-  jnlib_free(h);
+  if (reclaim)
+    jnlib_free (h);
 }
 
 
@@ -1284,9 +1287,14 @@ dotlock_release (dotlock_t h)
 
 /* Remove all lockfiles.  This is called by the atexit handler
    installed by this module but may also be called by other
-   termination handlers.  */
+   termination handlers.
+
+   When RECLAIM == 0, it doesn't reclaim memory allocated.
+   This is useful calling by signal handlers.
+*/
+
 void
-dotlock_remove_lockfiles (void)
+dotlock_remove_lockfiles (int reclaim)
 {
   dotlock_t h, h2;
 
@@ -1301,7 +1309,13 @@ dotlock_remove_lockfiles (void)
   while ( h )
     {
       h2 = h->next;
-      dotlock_destroy (h);
+      dotlock_destroy (h, reclaim);
       h = h2;
     }
 }
+
+void
+dotlock_remove_lockfiles_reclaim (void)
+{
+  dotlock_remove_lockfiles (1);
+}

Reply via email to