Make sure build_SYS_str_reasons() preserves errno
authorMatt Caswell <matt@openssl.org>
Wed, 21 Nov 2018 11:44:42 +0000 (11:44 +0000)
committerMatt Caswell <matt@openssl.org>
Mon, 10 Dec 2018 10:17:43 +0000 (10:17 +0000)
This function can end up being called during ERR_get_error() if we are
initialising. ERR_get_error() must preserve errno since it gets called via
SSL_get_error(). If that function returns SSL_ERROR_SYSCALL then you are
supposed to inspect errno.

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/7680)

crypto/err/err.c
e_os.h

index 11994c39215e302a3a90fa8c1e6801714ff099a8..bc671c911950275e5147ae9b99d1cb05f2f50bb1 100644 (file)
@@ -21,6 +21,7 @@
 #include "internal/thread_once.h"
 #include "internal/ctype.h"
 #include "internal/constant_time_locl.h"
+#include "e_os.h"
 
 static int err_load_strings(const ERR_STRING_DATA *str);
 
@@ -206,6 +207,7 @@ static void build_SYS_str_reasons(void)
     size_t cnt = 0;
     static int init = 1;
     int i;
+    int saveerrno = get_last_sys_error();
 
     CRYPTO_THREAD_write_lock(err_string_lock);
     if (!init) {
@@ -251,6 +253,8 @@ static void build_SYS_str_reasons(void)
     init = 0;
 
     CRYPTO_THREAD_unlock(err_string_lock);
+    /* openssl_strerror_r could change errno, but we want to preserve it */
+    set_sys_error(saveerrno);
     err_load_strings(SYS_str_reasons);
 }
 #endif
diff --git a/e_os.h b/e_os.h
index 6cdd35e6e1ffd5319458ec635962c4d9431a6902..9c0888e436e415c8a9804a31a904246a5cb22241 100644 (file)
--- a/e_os.h
+++ b/e_os.h
@@ -49,6 +49,7 @@
 
 # define get_last_sys_error()    errno
 # define clear_sys_error()       errno=0
+# define set_sys_error(e)        errno=(e)
 
 /********************************************************************
  The Microsoft section
 # ifdef WIN32
 #  undef get_last_sys_error
 #  undef clear_sys_error
+#  undef set_sys_error
 #  define get_last_sys_error()    GetLastError()
 #  define clear_sys_error()       SetLastError(0)
+#  define set_sys_error(e)        SetLastError(e)
 #  if !defined(WINNT)
 #   define WIN_CONSOLE_BUG
 #  endif