From 7d37818dacc87c21dfc9d2def5014657344875e3 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Mon, 23 May 2016 13:52:29 +0100 Subject: [PATCH] Use strerror_r()/strerror_s() instead of strerror() where possible The function strerror() is not thread safe. We should use strerror_r() where possible, or strerror_s() on Windows. RT#2267 Reviewed-by: Richard Levitte --- crypto/dso/dso_dl.c | 8 ++++++-- crypto/err/err.c | 6 +----- crypto/include/internal/cryptlib.h | 2 ++ crypto/o_str.c | 28 ++++++++++++++++++++++++++++ 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/crypto/dso/dso_dl.c b/crypto/dso/dso_dl.c index f5c51bfe85..bc29fb23e0 100644 --- a/crypto/dso/dso_dl.c +++ b/crypto/dso/dso_dl.c @@ -66,8 +66,10 @@ static int dl_load(DSO *dso) (dso->flags & DSO_FLAG_NO_NAME_TRANSLATION ? 0 : DYNAMIC_PATH), 0L); if (ptr == NULL) { + char errbuf[160]; DSOerr(DSO_F_DL_LOAD, DSO_R_LOAD_FAILED); - ERR_add_error_data(4, "filename(", filename, "): ", strerror(errno)); + if (openssl_strerror_r(errno, errbuf, sizeof(errbuf))) + ERR_add_error_data(4, "filename(", filename, "): ", errbuf); goto err; } if (!sk_push(dso->meth_data, (char *)ptr)) { @@ -130,8 +132,10 @@ static DSO_FUNC_TYPE dl_bind_func(DSO *dso, const char *symname) return (NULL); } if (shl_findsym(&ptr, symname, TYPE_UNDEFINED, &sym) < 0) { + char errbuf[160]; DSOerr(DSO_F_DL_BIND_FUNC, DSO_R_SYM_FAILURE); - ERR_add_error_data(4, "symname(", symname, "): ", strerror(errno)); + if (openssl_strerror_r(errno, errbuf, sizeof(errbuf))) + ERR_add_error_data(4, "symname(", symname, "): ", errbuf); return (NULL); } return ((DSO_FUNC_TYPE)sym); diff --git a/crypto/err/err.c b/crypto/err/err.c index 1035e4c749..9b679d9b48 100644 --- a/crypto/err/err.c +++ b/crypto/err/err.c @@ -220,12 +220,8 @@ static void build_SYS_str_reasons(void) str->error = (unsigned long)i; if (str->string == NULL) { char (*dest)[LEN_SYS_STR_REASON] = &(strerror_tab[i - 1]); - char *src = strerror(i); - if (src != NULL) { - strncpy(*dest, src, sizeof(*dest)); - (*dest)[sizeof(*dest) - 1] = '\0'; + if (openssl_strerror_r(i, *dest, sizeof(*dest))) str->string = *dest; - } } if (str->string == NULL) str->string = "unknown"; diff --git a/crypto/include/internal/cryptlib.h b/crypto/include/internal/cryptlib.h index 1327dca446..f2377d1c93 100644 --- a/crypto/include/internal/cryptlib.h +++ b/crypto/include/internal/cryptlib.h @@ -67,6 +67,8 @@ void OPENSSL_showfatal(const char *fmta, ...); extern int OPENSSL_NONPIC_relocated; void crypto_cleanup_all_ex_data_int(void); +int openssl_strerror_r(int errnum, char *buf, size_t buflen); + #ifdef __cplusplus } #endif diff --git a/crypto/o_str.c b/crypto/o_str.c index 0ee2c86d8b..98eb1631cb 100644 --- a/crypto/o_str.c +++ b/crypto/o_str.c @@ -258,3 +258,31 @@ char *OPENSSL_buf2hexstr(const unsigned char *buffer, long len) return tmp; } + +int openssl_strerror_r(int errnum, char *buf, size_t buflen) +{ +#if defined(OPENSSL_SYS_WINDOWS) + if (strerror_s(buf, buflen, errnum) == EINVAL) + return 0; + return 1; +#elif (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE + /* + * We can use "real" strerror_r. The OpenSSL version differs in that it + * gives 1 on success and 0 on failure for consistency with other OpenSSL + * functions. Real strerror_r does it the other way around + */ + return !strerror_r(errnum, buf, buflen); +#else + char *err; + /* Fall back to non-thread safe strerror()...its all we can do */ + if (buflen < 2) + return 0; + err = strerror(errnum); + /* Can this ever happen? */ + if (err == NULL) + return 0; + strncpy(buf, err, buflen - 1); + buf[buflen - 1] = '\0'; + return 1; +#endif +} -- GitLab