Skip to content

Commit 1edea69

Browse files
authored
Merge pull request #2360 from jan-cerny/issue2358
Fix segmentation fault with xmlsec1 >= 1.3
2 parents 186f151 + 4e6cfa5 commit 1edea69

1 file changed

Lines changed: 64 additions & 32 deletions

File tree

src/source/signature.c

Lines changed: 64 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
#include <stdlib.h>
2828
#include <string.h>
2929
#include <assert.h>
30+
#ifdef OSCAP_THREAD_SAFE
31+
#include <pthread.h>
32+
#endif
3033

3134
#include <libxml/tree.h>
3235
#include <libxml/xmlmemory.h>
@@ -46,6 +49,47 @@
4649
#include "oscap_source_priv.h"
4750
#include "signature_priv.h"
4851

52+
#ifdef OSCAP_THREAD_SAFE
53+
static pthread_once_t xmlsec_init_once = PTHREAD_ONCE_INIT;
54+
#else
55+
static bool xmlsec_init_done = false;
56+
#endif
57+
static int xmlsec_init_result = -1;
58+
59+
static void _xmlsec_init(void)
60+
{
61+
if (xmlSecInit() < 0) {
62+
oscap_seterr(OSCAP_EFAMILY_XML, "Xmlsec initialization failed.");
63+
return;
64+
}
65+
if (xmlSecCheckVersion() != 1) {
66+
oscap_seterr(OSCAP_EFAMILY_XML, "Loaded xmlsec library version is not compatible.");
67+
return;
68+
}
69+
if (xmlSecCryptoAppInit(NULL) < 0) {
70+
oscap_seterr(OSCAP_EFAMILY_XML, "Crypto initialization failed.");
71+
return;
72+
}
73+
if (xmlSecCryptoInit() < 0) {
74+
oscap_seterr(OSCAP_EFAMILY_XML, "Xmlsec-crypto initialization failed.");
75+
return;
76+
}
77+
xmlsec_init_result = 0;
78+
}
79+
80+
static int _xmlsec_ensure_init(void)
81+
{
82+
#ifdef OSCAP_THREAD_SAFE
83+
pthread_once(&xmlsec_init_once, _xmlsec_init);
84+
#else
85+
if (!xmlsec_init_done) {
86+
xmlsec_init_done = true;
87+
_xmlsec_init();
88+
}
89+
#endif
90+
return xmlsec_init_result;
91+
}
92+
4993
struct oscap_signature_ctx {
5094
const char *pubkey_pem; // path to the public key file in PEM format
5195
const char *pubkey_cert_pem; // path to the public key certificate file in PEM format
@@ -131,28 +175,20 @@ static int _oscap_signature_validate_doc(xmlDocPtr doc, oscap_document_type_t sc
131175
xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid);
132176
xsltSetDefaultSecurityPrefs(xsltSecPrefs);
133177

134-
/* Init xmlsec library */
135-
if (xmlSecInit() < 0) {
136-
oscap_seterr(OSCAP_EFAMILY_XML, "Xmlsec initialization failed.");
137-
return(-1);
138-
}
139-
140-
/* Check loaded library version */
141-
if (xmlSecCheckVersion() != 1) {
142-
oscap_seterr(OSCAP_EFAMILY_XML, "Loaded xmlsec library version is not compatible.");
143-
return(-1);
144-
}
145-
146-
/* Init crypto library */
147-
if (xmlSecCryptoAppInit(NULL) < 0) {
148-
oscap_seterr(OSCAP_EFAMILY_XML, "Crypto initialization failed.");
149-
return(-1);
150-
}
151-
152-
/* Init xmlsec-crypto library */
153-
if (xmlSecCryptoInit() < 0) {
154-
oscap_seterr(OSCAP_EFAMILY_XML, "Xmlsec-crypto initialization failed.");
155-
return(-1);
178+
/* Initialize xmlsec and crypto libraries once per process.
179+
*
180+
* xmlSecCryptoAppShutdown() calls OPENSSL_cleanup() which is
181+
* irreversible and destroys all process-global OpenSSL state
182+
* including threading locks. Other libraries in the same process
183+
* (e.g. librpm) continue to use OpenSSL after signature validation
184+
* completes. Calling OPENSSL_cleanup() while they are active causes
185+
* a segfault in CRYPTO_THREAD_write_lock.
186+
*
187+
* The xmlsec/OpenSSL libraries are designed to be initialized once
188+
* and remain active for the process lifetime. Treat them as such.
189+
*/
190+
if (_xmlsec_ensure_init() < 0) {
191+
goto cleanup;
156192
}
157193

158194
/* find Signature node */
@@ -261,22 +297,18 @@ static int _oscap_signature_validate_doc(xmlDocPtr doc, oscap_document_type_t sc
261297
}
262298

263299
cleanup:
264-
/* cleanup */
300+
/* cleanup per-validation resources only */
265301
if (dsigCtx != NULL)
266302
xmlSecDSigCtxDestroy(dsigCtx);
267303

268-
/* destroy keys manager */
269304
if (mngr != NULL)
270305
xmlSecKeysMngrDestroy(mngr);
271306

272-
/* Shutdown xmlsec-crypto library */
273-
xmlSecCryptoShutdown();
274-
275-
/* Shutdown crypto library */
276-
xmlSecCryptoAppShutdown();
277-
278-
/* Shutdown xmlsec library */
279-
xmlSecShutdown();
307+
/* Do NOT call xmlSecCryptoShutdown(), xmlSecCryptoAppShutdown(),
308+
* or xmlSecShutdown() here. These destroy process-global state
309+
* (including OPENSSL_cleanup()) that other libraries rely on.
310+
* The resources are cleaned up at process exit.
311+
*/
280312

281313
/* Shutdown libxslt/libxml */
282314
xsltFreeSecurityPrefs(xsltSecPrefs);

0 commit comments

Comments
 (0)