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); +}