diff options
author | Patrick Steinhardt <ps@pks.im> | 2018-01-03 12:54:42 +0000 |
---|---|---|
committer | Patrick Steinhardt <ps@pks.im> | 2018-01-03 12:54:42 +0000 |
commit | ba56f781a91487ad657e1a72888c914b1cec5de9 (patch) | |
tree | 18f7b495e1ccf15feb1e13413677e0d23e81adaf | |
parent | 75e1737a5173709b14b669bf08dae78232c6389d (diff) | |
download | libgit2-ba56f781a91487ad657e1a72888c914b1cec5de9.tar.gz |
streams: openssl: fix thread-safety for OpenSSL error messages
The function `ERR_error_string` can be invoked without providing a
buffer, in which case OpenSSL will simply return a string printed into a
static buffer. Obviously and as documented in ERR_error_string(3), this
is not thread-safe at all. As libgit2 is a library, though, it is easily
possible that other threads may be using OpenSSL at the same time, which
might lead to clobbered error strings.
Fix the issue by instead using a stack-allocated buffer. According to
the documentation, the caller has to provide a buffer of at least 256
bytes of size. While we do so, make sure that the buffer will never get
overflown by switching to `ERR_error_string_n` to specify the buffer's
size.
-rw-r--r-- | src/streams/openssl.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/src/streams/openssl.c b/src/streams/openssl.c index 2b246002f..133d1416d 100644 --- a/src/streams/openssl.c +++ b/src/streams/openssl.c @@ -282,8 +282,9 @@ static int ssl_set_error(SSL *ssl, int error) case SSL_ERROR_SYSCALL: e = ERR_get_error(); if (e > 0) { - giterr_set(GITERR_NET, "SSL error: %s", - ERR_error_string(e, NULL)); + char errmsg[256]; + ERR_error_string_n(e, errmsg, sizeof(errmsg)); + giterr_set(GITERR_NET, "SSL error: %s", errmsg); break; } else if (error < 0) { giterr_set(GITERR_OS, "SSL error: syscall failure"); @@ -293,10 +294,13 @@ static int ssl_set_error(SSL *ssl, int error) return GIT_EEOF; break; case SSL_ERROR_SSL: + { + char errmsg[256]; e = ERR_get_error(); - giterr_set(GITERR_NET, "SSL error: %s", - ERR_error_string(e, NULL)); + ERR_error_string_n(e, errmsg, sizeof(errmsg)); + giterr_set(GITERR_NET, "SSL error: %s", errmsg); break; + } case SSL_ERROR_NONE: case SSL_ERROR_ZERO_RETURN: default: @@ -640,8 +644,12 @@ out_err: int git_openssl__set_cert_location(const char *file, const char *path) { if (SSL_CTX_load_verify_locations(git__ssl_ctx, file, path) == 0) { + char errmsg[256]; + + ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg)); giterr_set(GITERR_SSL, "OpenSSL error: failed to load certificates: %s", - ERR_error_string(ERR_get_error(), NULL)); + errmsg); + return -1; } return 0; |