[PATCH] Prevent tail call optimization with _gcry_burn_stack

Jussi Kivilinna jussi.kivilinna at iki.fi
Thu Sep 26 11:54:06 CEST 2013


* src/g10lib.h (_gcry_burn_stack): Rename to __gcry_burn_stack.
(__gcry_burn_stack_dummy): New.
(_gcry_burn_stack): New macro.
* src/misc.c (_gcry_burn_stack): Rename to __gcry_burn_stack.
(__gcry_burn_stack_dummy): New.
--

Tail call optimization can turn _gcry_burn_stack call in to tail jump. When
this happens, stack pointer is restored to initial state of current function.
This causes problem for _gcry_burn_stack because its callers do not count in
current function stack depth.

One solution is to prevent gcry_burn_stack being tail optimized by inserting
dummy function call behind it.

(Another would be to add memory barrier 'asm volatile("":::"memory")' behind
every_gcry_burn_stack. This however requires GCC asm support from compiler.)

Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
---
 src/g10lib.h |    6 +++++-
 src/misc.c   |    7 ++++++-
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/src/g10lib.h b/src/g10lib.h
index 73ba683..9b342c3 100644
--- a/src/g10lib.h
+++ b/src/g10lib.h
@@ -250,7 +250,11 @@ int strcasecmp (const char *a, const char *b) _GCRY_GCC_ATTR_PURE;
 
 /* Stack burning.  */
 
-void _gcry_burn_stack (unsigned int bytes);
+void __gcry_burn_stack_dummy (void);
+void __gcry_burn_stack (unsigned int bytes);
+#define _gcry_burn_stack(bytes) \
+	do { __gcry_burn_stack (bytes); \
+	     __gcry_burn_stack_dummy (); } while(0)
 
 
 /* To avoid that a compiler optimizes certain memset calls away, these
diff --git a/src/misc.c b/src/misc.c
index a19e1e4..83a3a9e 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -363,7 +363,7 @@ _gcry_log_printmpi (const char *text, gcry_mpi_t mpi)
 
 
 void
-_gcry_burn_stack (unsigned int bytes)
+__gcry_burn_stack (unsigned int bytes)
 {
 #ifdef HAVE_VLA
     /* (bytes == 0 ? 1 : bytes) == (!bytes + bytes) */
@@ -382,6 +382,11 @@ _gcry_burn_stack (unsigned int bytes)
 }
 
 void
+__gcry_burn_stack_dummy (void)
+{
+}
+
+void
 _gcry_divide_by_zero (void)
 {
     gpg_err_set_errno (EDOM);




More information about the Gcrypt-devel mailing list