Skip to content

Commit 91df1db

Browse files
dgntedjpoole
authored andcommitted
fix system library error messages
previously, we'd log a lot of "unknown" error messages. this should fix that. Signed-off-by: Daniel Grimm <dgrimm@redhat.com> Signed-off-by: Ted Poole <tpoole@redhat.com>
1 parent 4c8674f commit 91df1db

File tree

3 files changed

+162
-1
lines changed

3 files changed

+162
-1
lines changed

bssl-compat/patch/include/openssl/err.h.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,4 @@ uncomment.sh "$1" --comment -h \
2828
--uncomment-macro OPENSSL_PUT_ERROR \
2929
--uncomment-func-decl ERR_put_error \
3030
--uncomment-macro-redef ERR_NUM_ERRORS \
31-
--sed '/#define ERR_PACK/i#define ERR_PACK(lib, reason) ossl_ERR_PACK(lib, 0, reason)'
31+
--sed '/#define ERR_PACK/i#define ERR_PACK(lib, reason) (lib == ossl_ERR_LIB_SYS) ? (ossl_ERR_SYSTEM_FLAG | reason) : ossl_ERR_PACK(lib, 0, reason)'

bssl-compat/source/err.cc

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <ossl.h>
33
#include <map>
44
#include <string>
5+
#include <cstring>
56

67

78
uint64_t o2b(uint64_t e) {
@@ -71,6 +72,12 @@ extern "C" uint32_t ERR_get_error(void) {
7172

7273

7374
extern "C" const char *ERR_lib_error_string(uint32_t packed_error) {
75+
// Handle system library errors like BoringSSL does
76+
// OpenSSL 3.x returns NULL for system errors, but BoringSSL returns "system library"
77+
if (ossl_ERR_SYSTEM_ERROR(packed_error)) {
78+
return "system library";
79+
}
80+
7481
const char *ret = ossl.ossl_ERR_lib_error_string(b2o(packed_error));
7582
return (ret ? ret : "unknown library");
7683
}
@@ -92,6 +99,21 @@ extern "C" uint32_t ERR_peek_last_error(void) {
9299

93100

94101
extern "C" const char *ERR_reason_error_string(uint32_t packed_error) {
102+
// Handle system library errors like BoringSSL does
103+
// For system errors, return strerror(errno) like BoringSSL does
104+
if (ossl_ERR_SYSTEM_ERROR(packed_error)) {
105+
uint32_t reason = ossl_ERR_GET_REASON(packed_error);
106+
// For some reason BoringSSL only calls strerror() for errno < 127, and just
107+
// returns the string "unknown error" for errno >= 127. This excludes some
108+
// valid errno values (on Linux at least). We delibrately differ from
109+
// BoringSSL here, and up the limit to 256 to ensure we don't hide any valid
110+
// error strings.
111+
if (reason > 0 && reason < 256) {
112+
return strerror(reason);
113+
}
114+
return "unknown error";
115+
}
116+
95117
/**
96118
* This is not an exhaustive list of errors; rather it is just the ones that
97119
* need to be translated for the Envoy tests to pass (yes some of the tests do

bssl-compat/test/test_err.cc

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#include <openssl/err.h>
33
#include <openssl/ssl.h>
44
#include <limits>
5+
#include <cstring>
6+
#include <cerrno>
57

68

79
TEST(ErrTest, test_ERR_func_error_string) {
@@ -50,3 +52,140 @@ TEST(ErrTest, test_SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM) {
5052
EXPECT_STREQ("NO_COMMON_SIGNATURE_ALGORITHMS", ERR_reason_error_string(e));
5153
EXPECT_STREQ("error:100000fd:SSL routines:OPENSSL_internal:NO_COMMON_SIGNATURE_ALGORITHMS", ERR_error_string_n(e, buf, sizeof(buf)));
5254
}
55+
56+
57+
/**
58+
* OpenSSL and BoringSSL pack errors (consisting of library & reason codes) into
59+
* a 32 bit integer using similar mechanisms, but with slightly different mask
60+
* and shift values, giving different values between the libraries. This is
61+
* mostly hidden by the use of macros like ERR_PACK(library, reason),
62+
* ERR_GET_LIB(error), ERR_GET_REASON(error), and library codes like
63+
* ERR_LIB_SSL, ERR_LIB_X509 etc.
64+
*
65+
* However, OpenSSL and BoringSSL pack _system errors_ very differently....
66+
*
67+
* BoringSSL packs system errors the same as all its other errors, by passing
68+
* ERR_LIB_SYS as the library code, and errno as the reason, to the
69+
* ERR_PACK(lib,reason) macro i.e. ERR_PACK(ERR_LIB_SYS, errno).
70+
*
71+
* OpenSSL _does not_ pack system errors with ERR_PACK(ERR_LIB_SYS, errno) as
72+
* one might expect. Instead, it uses a different special case mechanism of
73+
* OR-ing the special ERR_SYSTEM_FLAG (0x80000000) with the errno value i.e.
74+
* (ERR_SYSTEM_FLAG | errno).
75+
*
76+
* For example, to represent a EPIPE system error (0x20 on Linux):
77+
* - BoringSSL : ERR_PACK(ERR_LIB_SYS,EPIPE)) = 0x02000020
78+
* - OpenSSL : (ERR_SYSTEM_FLAG | EPIPE) = 0x80000020
79+
*
80+
* Since bssl-compat is trying to emulate BoringSSL's behavior, we need to
81+
* ensure that packing system errors using ERR_PACK() appears to work the same
82+
* way as BoringSSL (even though the resulting numeric values will be
83+
* different).
84+
*/
85+
TEST(ErrTest, test_ERR_PACK_system_error) {
86+
uint32_t packed = ERR_PACK(ERR_LIB_SYS, EPIPE);
87+
88+
EXPECT_EQ(EPIPE, 0x20); // Sanity check
89+
90+
#ifdef BSSL_COMPAT
91+
EXPECT_EQ(ossl_ERR_SYSTEM_FLAG, 0x80000000); // Sanity check
92+
// These checks will fail if we haven't modified bssl-compat's definition of
93+
// ERR_PACK(lib,reason) to handle OpenSSL's special case for system errors.
94+
EXPECT_EQ(packed, ossl_ERR_SYSTEM_FLAG | EPIPE);
95+
EXPECT_EQ(packed, 0x80000020);
96+
#else
97+
EXPECT_EQ(ERR_LIB_SYS, 2); // Sanity check
98+
EXPECT_EQ(packed, 0x02000020);
99+
#endif
100+
101+
// These should work idenically on BoringSSL and OpenSSL
102+
EXPECT_EQ(ERR_GET_LIB(packed), ERR_LIB_SYS);
103+
EXPECT_EQ(ERR_GET_REASON(packed), EPIPE);
104+
}
105+
106+
107+
TEST(ErrTest, test_system_error_ECONNRESET) {
108+
uint32_t err = ERR_PACK(ERR_LIB_SYS, ECONNRESET);
109+
110+
ASSERT_EQ(ECONNRESET, 0x68); // Sanity check
111+
112+
#ifdef BSSL_COMPAT
113+
EXPECT_EQ(err, 0x80000068); // OpenSSL packed value
114+
#else
115+
EXPECT_EQ(err, 0x02000068); // BoringSSL packed value
116+
#endif
117+
118+
EXPECT_EQ(ERR_LIB_SYS, ERR_GET_LIB(err));
119+
EXPECT_EQ(ECONNRESET, ERR_GET_REASON(err));
120+
121+
const char *lib = ERR_lib_error_string(err);
122+
ASSERT_NE(nullptr, lib);
123+
EXPECT_STREQ("system library", lib);
124+
125+
const char *reason = ERR_reason_error_string(err);
126+
ASSERT_NE(nullptr, reason);
127+
EXPECT_STREQ(strerror(ECONNRESET), reason);
128+
}
129+
130+
131+
TEST(ErrTest, test_system_error_EPIPE) {
132+
uint32_t err = ERR_PACK(ERR_LIB_SYS, EPIPE);
133+
134+
ASSERT_EQ(EPIPE, 0x20); // Sanity check
135+
136+
#ifdef BSSL_COMPAT
137+
EXPECT_EQ(err, 0x80000020); // OpenSSL packed value
138+
#else
139+
EXPECT_EQ(err, 0x02000020); // BoringSSL packed value
140+
#endif
141+
142+
EXPECT_EQ(ERR_LIB_SYS, ERR_GET_LIB(err));
143+
EXPECT_EQ(EPIPE, ERR_GET_REASON(err));
144+
145+
const char *lib = ERR_lib_error_string(err);
146+
ASSERT_NE(nullptr, lib);
147+
EXPECT_STREQ("system library", lib);
148+
149+
const char *reason = ERR_reason_error_string(err);
150+
ASSERT_NE(nullptr, reason);
151+
EXPECT_STREQ(strerror(EPIPE), reason);
152+
}
153+
154+
155+
TEST(ErrTest, test_system_error_ETIMEDOUT) {
156+
uint32_t err = ERR_PACK(ERR_LIB_SYS, ETIMEDOUT);
157+
158+
ASSERT_EQ(ETIMEDOUT, 0x6E); // Sanity check
159+
160+
#ifdef BSSL_COMPAT
161+
EXPECT_EQ(err, 0x8000006E); // OpenSSL packed value
162+
#else
163+
EXPECT_EQ(err, 0x0200006E); // BoringSSL packed value
164+
#endif
165+
166+
EXPECT_EQ(ERR_LIB_SYS, ERR_GET_LIB(err));
167+
EXPECT_EQ(ETIMEDOUT, ERR_GET_REASON(err));
168+
169+
const char *lib = ERR_lib_error_string(err);
170+
ASSERT_NE(nullptr, lib);
171+
EXPECT_STREQ("system library", lib);
172+
173+
const char *reason = ERR_reason_error_string(err);
174+
ASSERT_NE(nullptr, reason);
175+
EXPECT_STREQ(strerror(ETIMEDOUT), reason);
176+
}
177+
178+
179+
TEST(ErrTest, test_system_error_invalid_errno) {
180+
uint32_t err = ERR_PACK(ERR_LIB_SYS, 0xFFF);
181+
182+
EXPECT_EQ(ERR_LIB_SYS, ERR_GET_LIB(err));
183+
184+
const char *lib = ERR_lib_error_string(err);
185+
ASSERT_NE(nullptr, lib);
186+
EXPECT_STREQ("system library", lib);
187+
188+
const char *reason = ERR_reason_error_string(err);
189+
ASSERT_NE(nullptr, reason);
190+
EXPECT_STREQ("unknown error", reason);
191+
}

0 commit comments

Comments
 (0)