Compare commits

...

9 commits

Author SHA1 Message Date
Tim Wojtulewicz
a27cc89335 Remove checks for OpenSSL 1.x versions 2025-09-29 10:23:28 -07:00
Tim Wojtulewicz
686f100f0d Remove some additional LibreSSL checks 2025-09-29 10:23:28 -07:00
Arne Welzel
6af1459f5e Merge remote-tracking branch 'origin/topic/awelzel/4849-supervisor-signal-handle-tsan'
Some checks are pending
pre-commit / pre-commit (push) Waiting to run
* origin/topic/awelzel/4849-supervisor-signal-handle-tsan:
  Supervisor: Make last_signal atomic to squelch data race
2025-09-29 18:04:49 +02:00
Tim Wojtulewicz
3c16ee9667 Update docs submodule [nomail] 2025-09-29 08:21:10 -07:00
Arne Welzel
31d7df915e Supervisor: Make last_signal atomic to squelch data race
When the stem process terminates and SIGCHLD is sent to the supervisor,
the signal might be handled by the main thread or any other threads that
aren't blocking SIGCHLD explicitly. Convert last_signal to a std::atomic<int>
such that non-main threads can safely set last_signal without triggering
data race as reported by TSAN. This doesn't make it less racy to work
last_signal, but it appears we only use it for debug printing anyhow and
another option might have been to just remove last_signal altogether.

Follow-up for #4849
2025-09-29 14:50:20 +02:00
Arne Welzel
3abc1116a1 Merge remote-tracking branch 'origin/topic/awelzel/zeromq-fix-block-subscribe-before-init'
Some checks are pending
pre-commit / pre-commit (push) Waiting to run
* origin/topic/awelzel/zeromq-fix-block-subscribe-before-init:
  cluster/zeromq: Fix Cluster::subscribe() block if not initialized
2025-09-29 13:08:32 +02:00
Tim Wojtulewicz
0700427bac Merge remote-tracking branch 'origin/topic/vern/standalone-fixes2'
Some checks failed
pre-commit / pre-commit (push) Has been cancelled
* origin/topic/vern/standalone-fixes2:
  Fixes for -O gen-standalone-C++ for tracking BiFs, lambdas, attribute types, and independent globals
2025-09-26 14:19:49 -07:00
Arne Welzel
01666df3d7 cluster/zeromq: Fix Cluster::subscribe() block if not initialized
If Cluster::init() hasn't been invoked yet, Cluster::subscribe() with the
ZeroMQ backend would block because the main_inproc socket didn't
yet have a connection from the child thread. Prevent this by connecting
the main and child socket pair at construction time.

This will queue the subscriptions and start processing them once the
child thread has started.
2025-09-25 18:58:35 +02:00
Vern Paxson
550c7eb0a7 Fixes for -O gen-standalone-C++ for tracking BiFs, lambdas, attribute types, and independent globals 2025-09-24 17:34:35 -07:00
18 changed files with 160 additions and 217 deletions

34
CHANGES
View file

@ -1,3 +1,37 @@
8.1.0-dev.612 | 2025-09-29 18:04:24 +0200
* Supervisor: Make last_signal atomic to squelch data race (Arne Welzel, Corelight)
When the stem process terminates and SIGCHLD is sent to the supervisor,
the signal might be handled by the main thread or any other threads that
aren't blocking SIGCHLD explicitly. Convert last_signal to a std::atomic<int>
such that non-main threads can safely set last_signal without triggering
data race as reported by TSAN. This doesn't make it less racy to work
last_signal, but it appears we only use it for debug printing anyhow and
another option might have been to just remove last_signal altogether.
Follow-up for #4849
8.1.0-dev.610 | 2025-09-29 08:21:01 -0700
* Update docs submodule [nomail] (Tim Wojtulewicz, Corelight)
8.1.0-dev.609 | 2025-09-29 13:08:15 +0200
* cluster/zeromq: Fix Cluster::subscribe() block if not initialized (Arne Welzel, Corelight)
If Cluster::init() hasn't been invoked yet, Cluster::subscribe() with the
ZeroMQ backend would block because the main_inproc socket didn't
yet have a connection from the child thread. Prevent this by connecting
the main and child socket pair at construction time.
This will queue the subscriptions and start processing them once the
child thread has started.
8.1.0-dev.607 | 2025-09-26 14:19:40 -0700
* Fixes for -O gen-standalone-C++ for tracking BiFs, lambdas, attribute types, and independent globals (Vern Paxson, Corelight)
8.1.0-dev.605 | 2025-09-26 11:19:17 -0700
* OpaqueVal, OCSP, X509: drop outdated LibreSSL guards to fix OpenBSD (Klemens Nanni)

View file

@ -1 +1 @@
8.1.0-dev.605
8.1.0-dev.612

2
doc

@ -1 +1 @@
Subproject commit 2731def9159247e6da8a3191783c89683363689c
Subproject commit 8f38ae2fd563314393eb1ca58c827d26e9966520

View file

@ -27,10 +27,6 @@
#include "zeek/probabilistic/BloomFilter.h"
#include "zeek/probabilistic/CardinalityCounter.h"
#if ( OPENSSL_VERSION_NUMBER < 0x10100000L )
inline void* EVP_MD_CTX_md_data(const EVP_MD_CTX* ctx) { return ctx->md_data; }
#endif
#if ( OPENSSL_VERSION_NUMBER < 0x30000000L )
#include <openssl/md5.h>
#endif

View file

@ -85,6 +85,7 @@ ZeroMQBackend::ZeroMQBackend(std::unique_ptr<EventSerializer> es, std::unique_pt
: ThreadedBackend("ZeroMQ", std::move(es), std::move(ls), std::move(ehs),
new zeek::detail::OnLoopProcess<ThreadedBackend, QueueMessage>(this, "ZeroMQ", onloop_queue_hwm)),
main_inproc(zmq::socket_t(ctx, zmq::socket_type::pair)),
child_inproc(zmq::socket_t(ctx, zmq::socket_type::pair)),
// Counters for block and drop metrics.
total_xpub_drops(
zeek::telemetry_mgr->CounterInstance("zeek", "cluster_zeromq_xpub_drops", {},
@ -94,7 +95,13 @@ ZeroMQBackend::ZeroMQBackend(std::unique_ptr<EventSerializer> es, std::unique_pt
"Number of received events dropped due to OnLoop queue full.")),
total_msg_errors(
zeek::telemetry_mgr->CounterInstance("zeek", "cluster_zeromq_msg_errors", {},
"Number of events with the wrong number of message parts.")) {}
"Number of events with the wrong number of message parts.")) {
// Establish the socket connection between main thread and child thread
// already in the constructor. This allows Subscribe() and Unsubscribe()
// calls to be delayed until DoInit() was called.
main_inproc.bind("inproc://inproc-bridge");
child_inproc.connect("inproc://inproc-bridge");
}
ZeroMQBackend::~ZeroMQBackend() {
try {
@ -169,10 +176,11 @@ void ZeroMQBackend::DoTerminate() {
ctx.shutdown();
// Close the sockets that are used from the main thread,
// the remaining sockets were closed by self_thread during
// shutdown already.
// the remaining sockets except for the child_inproc one
// were closed by self_thread during shutdown already.
log_push.close();
main_inproc.close();
child_inproc.close();
ZEROMQ_DEBUG("Closing ctx");
ctx.close();
@ -197,7 +205,6 @@ bool ZeroMQBackend::DoInit() {
xpub = zmq::socket_t(ctx, zmq::socket_type::xpub);
log_push = zmq::socket_t(ctx, zmq::socket_type::push);
log_pull = zmq::socket_t(ctx, zmq::socket_type::pull);
child_inproc = zmq::socket_t(ctx, zmq::socket_type::pair);
xpub.set(zmq::sockopt::linger, linger_ms);
@ -286,10 +293,6 @@ bool ZeroMQBackend::DoInit() {
//
// https://funcptr.net/2012/09/10/zeromq---edge-triggered-notification/
// Setup connectivity between main and child thread.
main_inproc.bind("inproc://inproc-bridge");
child_inproc.connect("inproc://inproc-bridge");
// Thread is joined in backend->DoTerminate(), backend outlives it.
self_thread = std::thread([](auto* backend) { backend->Run(); }, this);
@ -634,7 +637,6 @@ void ZeroMQBackend::Run() {
// Called when Run() terminates.
auto deferred_close = util::Deferred([this]() {
child_inproc.close();
xpub.close();
xsub.close();
log_pull.close();

View file

@ -12,11 +12,6 @@
#include "zeek/Reporter.h"
#if ( OPENSSL_VERSION_NUMBER < 0x10100000L ) || defined(LIBRESSL_VERSION_NUMBER)
#define EVP_MD_CTX_new EVP_MD_CTX_create
#define EVP_MD_CTX_free EVP_MD_CTX_destroy
#endif
static_assert(ZEEK_MD5_DIGEST_LENGTH == MD5_DIGEST_LENGTH);
static_assert(ZEEK_SHA_DIGEST_LENGTH == SHA_DIGEST_LENGTH);

View file

@ -26,28 +26,11 @@ namespace zeek::file_analysis::detail {
static constexpr size_t OCSP_STRING_BUF_SIZE = 2048;
static bool OCSP_RESPID_bio(OCSP_BASICRESP* basic_resp, BIO* bio) {
#if ( OPENSSL_VERSION_NUMBER < 0x10100000L )
ASN1_OCTET_STRING* key = nullptr;
X509_NAME* name = nullptr;
if ( ! basic_resp->tbsResponseData )
return false;
auto resp_id = basic_resp->tbsResponseData->responderId;
if ( resp_id->type == V_OCSP_RESPID_NAME )
name = resp_id->value.byName;
else if ( resp_id->type == V_OCSP_RESPID_KEY )
key = resp_id->value.byKey;
else
return false;
#else
const ASN1_OCTET_STRING* key = nullptr;
const X509_NAME* name = nullptr;
if ( ! OCSP_resp_get0_id(basic_resp, &key, &name) )
return false;
#endif
if ( name )
X509_NAME_print_ex(bio, name, 0, XN_FLAG_ONELINE);
@ -150,8 +133,6 @@ bool OCSP::EndOfFile() {
return true;
}
#if ( OPENSSL_VERSION_NUMBER >= 0x10100000L )
struct ASN1Seq {
ASN1Seq(const unsigned char** der_in, long length) { decoded = d2i_ASN1_SEQUENCE_ANY(nullptr, der_in, length); }
@ -345,7 +326,6 @@ static uint64_t parse_request_version(OCSP_REQUEST* req) {
OPENSSL_free(der_req_dat);
return asn1_int;
}
#endif
void OCSP::ParseRequest(OCSP_REQUEST* req) {
char buf[OCSP_STRING_BUF_SIZE]; // we need a buffer for some of the openssl functions
@ -353,13 +333,8 @@ void OCSP::ParseRequest(OCSP_REQUEST* req) {
uint64_t version = 0;
#if ( OPENSSL_VERSION_NUMBER < 0x10100000L )
if ( req->tbsRequest->version )
version = (uint64_t)ASN1_INTEGER_get(req->tbsRequest->version);
#else
version = parse_request_version(req);
// TODO: try to parse out general name ?
#endif
if ( ocsp_request )
event_mgr.Enqueue(ocsp_request, GetFile()->ToVal(), val_mgr->Count(version));
@ -425,20 +400,10 @@ void OCSP::ParseResponse(OCSP_RESPONSE* resp) {
if ( ! basic_resp )
goto clean_up;
#if ( OPENSSL_VERSION_NUMBER < 0x10100000L )
resp_data = basic_resp->tbsResponseData;
if ( ! resp_data )
goto clean_up;
#endif
vl.emplace_back(GetFile()->ToVal());
vl.emplace_back(std::move(status_val));
#if ( OPENSSL_VERSION_NUMBER < 0x10100000L )
vl.emplace_back(val_mgr->Count((uint64_t)ASN1_INTEGER_get(resp_data->version)));
#else
vl.emplace_back(parse_basic_resp_data_version(basic_resp));
#endif
// responderID
if ( OCSP_RESPID_bio(basic_resp, bio) ) {
@ -452,11 +417,7 @@ void OCSP::ParseResponse(OCSP_RESPONSE* resp) {
}
// producedAt
#if ( OPENSSL_VERSION_NUMBER < 0x10100000L )
produced_at = resp_data->producedAt;
#else
produced_at = OCSP_resp_get0_produced_at(basic_resp);
#endif
vl.emplace_back(make_intrusive<TimeVal>(GetTimeFromAsn1(produced_at, GetFile(), reporter)));
@ -477,11 +438,7 @@ void OCSP::ParseResponse(OCSP_RESPONSE* resp) {
// cert id
const OCSP_CERTID* cert_id = nullptr;
#if ( OPENSSL_VERSION_NUMBER < 0x10100000L )
cert_id = single_resp->certId;
#else
cert_id = OCSP_SINGLERESP_get0_id(single_resp);
#endif
ocsp_add_cert_id(cert_id, &rvl, bio);
BIO_reset(bio);
@ -550,14 +507,7 @@ void OCSP::ParseResponse(OCSP_RESPONSE* resp) {
}
}
#if ( OPENSSL_VERSION_NUMBER < 0x10100000L )
i2a_ASN1_OBJECT(bio, basic_resp->signatureAlgorithm->algorithm);
len = BIO_read(bio, buf, sizeof(buf));
vl.emplace_back(make_intrusive<StringVal>(len, buf));
BIO_reset(bio);
#else
vl.emplace_back(parse_basic_resp_sig_alg(basic_resp, bio, buf, sizeof(buf)));
#endif
// i2a_ASN1_OBJECT(bio, basic_resp->signature);
// len = BIO_read(bio, buf, sizeof(buf));
@ -567,11 +517,7 @@ void OCSP::ParseResponse(OCSP_RESPONSE* resp) {
certs_vector = new VectorVal(id::find_type<VectorType>("x509_opaque_vector"));
vl.emplace_back(AdoptRef{}, certs_vector);
#if ( OPENSSL_VERSION_NUMBER < 0x10100000L )
certs = basic_resp->certs;
#else
certs = OCSP_resp_get0_certs(basic_resp);
#endif
if ( certs ) {
int num_certs = sk_X509_num(certs);

View file

@ -161,13 +161,9 @@ RecordValPtr X509::ParseCertificate(X509Val* cert_val, file_analysis::File* f) {
pX509Cert->Assign(7, buf);
#if ( OPENSSL_VERSION_NUMBER < 0x10100000L )
i2a_ASN1_OBJECT(bio, ssl_cert->sig_alg->algorithm);
#else
const ASN1_OBJECT* alg;
X509_ALGOR_get0(&alg, nullptr, nullptr, X509_get0_tbs_sigalg(ssl_cert));
i2a_ASN1_OBJECT(bio, alg);
#endif
len = BIO_gets(bio, buf, sizeof(buf));
pX509Cert->Assign(13, make_intrusive<StringVal>(len, buf));
BIO_free(bio);
@ -349,11 +345,7 @@ void X509::ParseSAN(X509_EXTENSION* ext) {
}
auto len = ASN1_STRING_length(gen->d.ia5);
#if ( OPENSSL_VERSION_NUMBER < 0x10100000L ) || defined(LIBRESSL_VERSION_NUMBER)
const char* name = (const char*)ASN1_STRING_data(gen->d.ia5);
#else
const char* name = (const char*)ASN1_STRING_get0_data(gen->d.ia5);
#endif
auto bs = make_intrusive<StringVal>(len, name);
switch ( gen->type ) {

View file

@ -9,55 +9,6 @@
#include "zeek/OpaqueVal.h"
#include "zeek/file_analysis/analyzer/x509/X509Common.h"
#if ( OPENSSL_VERSION_NUMBER < 0x10002000L )
#define X509_get_signature_nid(x) OBJ_obj2nid((x)->sig_alg->algorithm)
#endif
#if ( OPENSSL_VERSION_NUMBER < 0x1010000fL )
#define X509_OBJECT_new() (X509_OBJECT*)malloc(sizeof(X509_OBJECT))
#define X509_OBJECT_free(a) free(a)
#define OCSP_resp_get0_certs(x) (x)->certs
#define EVP_PKEY_get0_DSA(p) ((p)->pkey.dsa)
#define EVP_PKEY_get0_EC_KEY(p) ((p)->pkey.ec)
#define EVP_PKEY_get0_RSA(p) ((p)->pkey.rsa)
#if ! defined(LIBRESSL_VERSION_NUMBER) || (LIBRESSL_VERSION_NUMBER < 0x2070000fL)
#define OCSP_SINGLERESP_get0_id(s) (s)->certId
static X509* X509_OBJECT_get0_X509(const X509_OBJECT* a) {
if ( a == nullptr || a->type != X509_LU_X509 )
return nullptr;
return a->data.x509;
}
static void DSA_get0_pqg(const DSA* d, const BIGNUM** p, const BIGNUM** q, const BIGNUM** g) {
if ( p != nullptr )
*p = d->p;
if ( q != nullptr )
*q = d->q;
if ( g != nullptr )
*g = d->g;
}
static void RSA_get0_key(const RSA* r, const BIGNUM** n, const BIGNUM** e, const BIGNUM** d) {
if ( n != nullptr )
*n = r->n;
if ( e != nullptr )
*e = r->e;
if ( d != nullptr )
*d = r->d;
}
#endif
#endif
namespace zeek::file_analysis::detail {
class X509Val;

View file

@ -65,19 +65,8 @@ X509* x509_get_ocsp_signer(const STACK_OF(X509)* certs,
const ASN1_OCTET_STRING* key = nullptr;
const X509_NAME* name = nullptr;
#if ( OPENSSL_VERSION_NUMBER < 0x10100000L )
OCSP_RESPID* resp_id = basic_resp->tbsResponseData->responderId;
if ( resp_id->type == V_OCSP_RESPID_NAME )
name = resp_id->value.byName;
else if ( resp_id->type == V_OCSP_RESPID_KEY )
key = resp_id->value.byKey;
else
return nullptr;
#else
if ( ! OCSP_resp_get0_id(basic_resp, &key, &name) )
return nullptr;
#endif
if ( name )
return X509_find_by_subject(const_cast<STACK_OF(X509)*>(certs),
@ -359,11 +348,7 @@ function x509_ocsp_verify%(certs: x509_opaque_vector, ocsp_reply: string, root_c
// Because we actually want to be able to give nice error messages that show why we were
// not able to verify the OCSP response - do our own verification logic first.
#if ( OPENSSL_VERSION_NUMBER < 0x10100000L )
signer = x509_get_ocsp_signer(basic->certs, basic);
#else
signer = x509_get_ocsp_signer(OCSP_resp_get0_certs(basic), basic);
#endif
/*
Do this perhaps - OpenSSL also cannot do it, so I do not really feel bad about it.
@ -730,12 +715,7 @@ function sct_verify%(cert: opaque of x509, logid: string, log_key: string, signa
uint32_t cert_length;
if ( precert )
{
#if ( OPENSSL_VERSION_NUMBER < 0x10002000L )
x->cert_info->enc.modified = 1;
cert_length = i2d_X509_CINF(x->cert_info, &cert_out);
#else
cert_length = i2d_re_X509_tbs(x, &cert_out);
#endif
data.append(reinterpret_cast<const char*>(issuer_key_hash->Bytes()), issuer_key_hash->Len());
}
else
@ -1058,11 +1038,7 @@ function x509_check_cert_hostname%(cert_opaque: opaque of x509, hostname: string
continue;
std::size_t len = ASN1_STRING_length(gen->d.ia5);
#if ( OPENSSL_VERSION_NUMBER < 0x10100000L ) || defined(LIBRESSL_VERSION_NUMBER)
auto* name = reinterpret_cast<const char*>(ASN1_STRING_data(gen->d.ia5));
#else
auto* name = reinterpret_cast<const char*>(ASN1_STRING_get0_data(gen->d.ia5));
#endif
std::string_view nameview {name, len};
if ( check_hostname(hostview, nameview) )
{

View file

@ -83,9 +83,22 @@ void CPPCompile::Compile(bool report_uncompilable) {
accessed_globals.insert(g);
for ( auto& ag : pf->AllGlobals() )
all_accessed_globals.insert(ag);
for ( auto& l : pf->Lambdas() )
// We might not have profiled this previously if none
// of the functions refer to the global. This can
// happen for example for a global "const" table that's
// made available for external lookup use.
pfs->ProfileLambda(l);
}
}
for ( auto& g : pfs->BiFGlobals() )
all_accessed_globals.insert(g);
for ( auto& t : pfs->MainTypes() )
if ( obj_matches_opt_files(t) == AnalyzeDecision::SHOULD )
rep_types.insert(TypeRep(t));
for ( auto& l : pfs->Lambdas() )
if ( obj_matches_opt_files(l) == AnalyzeDecision::SHOULD )
accessed_lambdas.insert(l);

View file

@ -622,6 +622,20 @@ ProfileFuncs::ProfileFuncs(std::vector<FuncInfo>& funcs, is_compilable_pred pred
ComputeSideEffects();
}
void ProfileFuncs::ProfileLambda(const LambdaExpr* l) {
if ( lambdas.contains(l) )
return;
lambdas.insert(l);
pending_exprs.push_back(l);
do
DrainPendingExprs();
while ( ! pending_exprs.empty() );
AnalyzeLambdaProfile(l);
}
bool ProfileFuncs::IsTableWithDefaultAggr(const Type* t) {
auto analy = tbl_has_aggr_default.find(t);
if ( analy != tbl_has_aggr_default.end() )
@ -848,14 +862,22 @@ void ProfileFuncs::ComputeBodyHashes(std::vector<FuncInfo>& funcs) {
ComputeProfileHash(f.ProfilePtr());
}
for ( auto& l : lambdas ) {
for ( auto& l : lambdas )
AnalyzeLambdaProfile(l);
}
void ProfileFuncs::AnalyzeLambdaProfile(const LambdaExpr* l) {
if ( processed_lambdas.contains(l) )
return;
processed_lambdas.insert(l);
auto pf = ExprProf(l);
func_profs[l->PrimaryFunc().get()] = pf;
lambda_primaries[l->Name()] = l->PrimaryFunc().get();
if ( compute_func_hashes || ! pf->HasHashVal() )
ComputeProfileHash(pf);
}
}
void ProfileFuncs::ComputeProfileHash(std::shared_ptr<ProfileFunc> pf) {

View file

@ -366,6 +366,10 @@ public:
ProfileFuncs(std::vector<FuncInfo>& funcs, is_compilable_pred pred, bool compute_func_hashes,
bool full_record_hashes);
// Used to profile additional lambdas that (potentially) weren't part
// of the overall function profiling.
void ProfileLambda(const LambdaExpr* l);
// The following accessors provide a global profile across all of
// the (non-skipped) functions in "funcs". See the comments for
// the associated member variables for documentation.
@ -449,6 +453,9 @@ protected:
// Compute hashes to associate with each function
void ComputeBodyHashes(std::vector<FuncInfo>& funcs);
// For a given lambda, completes analysis of its profile.
void AnalyzeLambdaProfile(const LambdaExpr* l);
// Compute the hash associated with a single function profile.
void ComputeProfileHash(std::shared_ptr<ProfileFunc> pf);
@ -540,6 +547,10 @@ protected:
// And for lambda's.
std::unordered_set<const LambdaExpr*> lambdas;
// Lambdas that we have already processed. An optimization to avoid
// unnecessary work.
std::unordered_set<const LambdaExpr*> processed_lambdas;
// Names of generated events.
std::unordered_set<std::string> events;

View file

@ -415,7 +415,7 @@ static ForkResult fork_with_stdio_redirect(const char* where) {
void Supervisor::HandleChildSignal() {
if ( last_signal >= 0 ) {
DBG_LOG(DBG_SUPERVISOR, "Supervisor received signal %d", last_signal);
DBG_LOG(DBG_SUPERVISOR, "Supervisor received signal %d", last_signal.load());
last_signal = -1;
}

View file

@ -3,6 +3,7 @@
#pragma once
#include <sys/types.h>
#include <atomic>
#include <chrono>
#include <map>
#include <memory>
@ -323,7 +324,7 @@ private:
Config config;
pid_t stem_pid;
int last_signal = -1;
std::atomic<int> last_signal = -1;
std::unique_ptr<detail::PipePair> stem_pipe;
detail::LineBufferedPipe stem_stdout;
detail::LineBufferedPipe stem_stderr;

View file

@ -97,58 +97,6 @@ int perftools_leaks = 0;
int perftools_profile = 0;
#endif
#if OPENSSL_VERSION_NUMBER < 0x10100000L
struct CRYPTO_dynlock_value {
std::mutex mtx;
};
namespace {
std::unique_ptr<std::mutex[]> ssl_mtx_tbl;
void ssl_lock_fn(int mode, int n, const char*, int) {
if ( mode & CRYPTO_LOCK )
ssl_mtx_tbl[static_cast<size_t>(n)].lock();
else
ssl_mtx_tbl[static_cast<size_t>(n)].unlock();
}
CRYPTO_dynlock_value* ssl_dynlock_create(const char*, int) { return new CRYPTO_dynlock_value; }
void ssl_dynlock_lock(int mode, CRYPTO_dynlock_value* ptr, const char*, int) {
if ( mode & CRYPTO_LOCK )
ptr->mtx.lock();
else
ptr->mtx.unlock();
}
void ssl_dynlock_destroy(CRYPTO_dynlock_value* ptr, const char*, int) { delete ptr; }
void do_ssl_init() {
ERR_load_crypto_strings();
OPENSSL_add_all_algorithms_conf();
SSL_library_init();
SSL_load_error_strings();
ssl_mtx_tbl.reset(new std::mutex[CRYPTO_num_locks()]);
CRYPTO_set_locking_callback(ssl_lock_fn);
CRYPTO_set_dynlock_create_callback(ssl_dynlock_create);
CRYPTO_set_dynlock_lock_callback(ssl_dynlock_lock);
CRYPTO_set_dynlock_destroy_callback(ssl_dynlock_destroy);
}
void do_ssl_deinit() {
ERR_free_strings();
EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
CRYPTO_set_locking_callback(nullptr);
CRYPTO_set_dynlock_create_callback(nullptr);
CRYPTO_set_dynlock_lock_callback(nullptr);
CRYPTO_set_dynlock_destroy_callback(nullptr);
ssl_mtx_tbl.reset();
}
} // namespace
#else
namespace {
void do_ssl_init() { OPENSSL_init_ssl(0, nullptr); }
@ -160,7 +108,6 @@ void do_ssl_deinit() {
}
} // namespace
#endif
zeek::ValManager* zeek::val_mgr = nullptr;
zeek::packet_analysis::Manager* zeek::packet_mgr = nullptr;

View file

@ -0,0 +1,2 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
test(), 42

View file

@ -0,0 +1,55 @@
# @TEST-DOC: Regression test Cluster::subscribe() blocking if called in a high-priority zeek_init() handler
#
# @TEST-REQUIRES: have-zeromq
#
# @TEST-GROUP: cluster-zeromq
#
# @TEST-PORT: XPUB_PORT
# @TEST-PORT: XSUB_PORT
# @TEST-PORT: LOG_PULL_PORT
#
# @TEST-EXEC: cp $FILES/zeromq/cluster-layout-simple.zeek cluster-layout.zeek
# @TEST-EXEC: cp $FILES/zeromq/test-bootstrap.zeek zeromq-test-bootstrap.zeek
#
# @TEST-EXEC: zeek --parse-only ./manager.zeek ./worker.zeek
#
# @TEST-EXEC: btest-bg-run manager "ZEEKPATH=$ZEEKPATH:.. && CLUSTER_NODE=manager zeek -b ../manager.zeek >out"
# @TEST-EXEC: btest-bg-run worker "ZEEKPATH=$ZEEKPATH:.. && CLUSTER_NODE=worker-1 zeek -b ../worker.zeek >out"
#
# @TEST-EXEC: btest-bg-wait 30
# @TEST-EXEC: btest-diff ./manager/out
# @TEST-START-FILE common.zeek
@load ./zeromq-test-bootstrap
global test: event(c: count) &is_used;
# @TEST-END-FILE
# @TEST-START-FILE manager.zeek
@load ./common.zeek
event zeek_init() &priority=1000000
{
Cluster::subscribe("test.early");
}
event test(c: count)
{
print "test()", c;
}
event Cluster::node_down(name: string, id: string)
{
terminate();
}
# @TEST-END-FILE
# @TEST-START-FILE worker.zeek
@load ./common.zeek
event Cluster::node_up(name: string, id: string)
{
Cluster::publish("test.early", test, 42);
terminate();
}
# @TEST-END-FILE