Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dird: fix tls reload crash #1249

Merged
merged 4 commits into from Oct 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -52,6 +52,7 @@ and since Bareos version 20 this project adheres to [Semantic Versioning](https:
- build: run a build and test with sanitizers enabled [PR #1244]

### Fixed
- dird: fix possible crash in tls context on configuration reload [PR #1249]
- dird: RunScript fixes [PR #1217]
- fix show command output for RunScript RunsOnClient
- fix show verbose for RunScripts
Expand Down
4 changes: 2 additions & 2 deletions core/src/dird/reload.cc
Expand Up @@ -255,7 +255,7 @@ bool DoReloadConfig()

DbSqlPoolFlush();

auto backup_table = my_config->BackupResourceTable();
auto backup_container = my_config->BackupResourcesContainer();
Dmsg0(100, "Reloading config file\n");


Expand All @@ -281,7 +281,7 @@ bool DoReloadConfig()
my_config->get_base_config_path().c_str());

Jmsg(nullptr, M_ERROR, 0, _("Resetting to previous configuration.\n"));
my_config->RestoreResourceTable(std::move(backup_table));
my_config->RestoreResourcesContainer(std::move(backup_container));
// me is changed above by CheckResources()
me = (DirectorResource*)my_config->GetNextRes(R_DIRECTOR, nullptr);
assert(me);
Expand Down
15 changes: 9 additions & 6 deletions core/src/lib/parse_conf.cc
Expand Up @@ -487,26 +487,29 @@ bool ConfigurationParser::FindConfigPath(PoolMem& full_path)
return found;
}

// swap the previously saved configuration_resources_previous_ with
// configuration_resources_ and release the configuration_resources_previous_
void ConfigurationParser::RestoreResourceTable(
void ConfigurationParser::RestoreResourcesContainer(
std::shared_ptr<ConfigResourcesContainer>&& backup_table)
{
std::swap(config_resources_container_, backup_table);
backup_table.reset();
}

// copy the current resource table to configuration_resources_backup_
// and create a new empty config_resources_container_
std::shared_ptr<ConfigResourcesContainer>
ConfigurationParser::BackupResourceTable()
ConfigurationParser::BackupResourcesContainer()
{
auto backup_table = config_resources_container_;
config_resources_container_
= std::make_shared<ConfigResourcesContainer>(this);
return backup_table;
}

std::shared_ptr<ConfigResourcesContainer>
ConfigurationParser::GetResourcesContainer()
{
return config_resources_container_;
}


bool ConfigurationParser::RemoveResource(int rcode, const char* name)
{
int rindex = rcode;
Expand Down
5 changes: 3 additions & 2 deletions core/src/lib/parse_conf.h
Expand Up @@ -256,8 +256,9 @@ class ConfigurationParser {
const std::string& get_base_config_path() const { return used_config_path_; }
void FreeResources();

std::shared_ptr<ConfigResourcesContainer> BackupResourceTable();
void RestoreResourceTable(std::shared_ptr<ConfigResourcesContainer>&&);
std::shared_ptr<ConfigResourcesContainer> GetResourcesContainer();
std::shared_ptr<ConfigResourcesContainer> BackupResourcesContainer();
void RestoreResourcesContainer(std::shared_ptr<ConfigResourcesContainer>&&);

void InitResource(int rcode,
ResourceItem items[],
Expand Down
4 changes: 3 additions & 1 deletion core/src/lib/tls_openssl.cc
Expand Up @@ -75,7 +75,9 @@ void TlsOpenSsl::SetTlsPskServerContext(ConfigurationParser* config)
} else if (!config) {
Dmsg0(50, "Could not prepare TLS_PSK SERVER callback (no config)\n");
} else {
Dmsg0(50, "Preparing TLS_PSK SERVER callback\n");
// keep a shared_ptr to the current config, so a reload won't
// free the memory we're going to use in the private context
d_->config_table_ = config->GetResourcesContainer();
SSL_CTX_set_ex_data(
d_->openssl_ctx_,
TlsOpenSslPrivate::SslCtxExDataIndex::kConfigurationParserPtr,
Expand Down
3 changes: 2 additions & 1 deletion core/src/lib/tls_openssl.h
@@ -1,7 +1,7 @@
/*
BAREOS® - Backup Archiving REcovery Open Sourced

Copyright (C) 2018-2020 Bareos GmbH & Co. KG
Copyright (C) 2018-2022 Bareos GmbH & Co. KG

This program is Free Software; you can redistribute it and/or
modify it under the terms of version three of the GNU Affero General Public
Expand All @@ -27,6 +27,7 @@
#include <memory>

class TlsOpenSslPrivate;
class ConfigResourcesContainer;

class TlsOpenSsl : public Tls {
public:
Expand Down
9 changes: 1 addition & 8 deletions core/src/lib/tls_openssl_private.cc
Expand Up @@ -2,7 +2,7 @@
BAREOS® - Backup Archiving REcovery Open Sourced

Copyright (C) 2005-2010 Free Software Foundation Europe e.V.
Copyright (C) 2018-2020 Bareos GmbH & Co. KG
Copyright (C) 2018-2022 Bareos GmbH & Co. KG

This program is Free Software; you can redistribute it and/or
modify it under the terms of version three of the GNU Affero General Public
Expand Down Expand Up @@ -54,13 +54,6 @@ const std::string TlsOpenSslPrivate::tls_default_ciphers_{


TlsOpenSslPrivate::TlsOpenSslPrivate()
: openssl_(nullptr)
, openssl_ctx_(nullptr)
, openssl_conf_ctx_(nullptr)
, tcp_file_descriptor_(0)
, pem_callback_(nullptr)
, pem_userdata_(nullptr)
, verify_peer_(false)
{
Dmsg0(100, "Construct TlsOpenSslPrivate\n");

Expand Down
19 changes: 10 additions & 9 deletions core/src/lib/tls_openssl_private.h
Expand Up @@ -2,7 +2,7 @@
BAREOS® - Backup Archiving REcovery Open Sourced

Copyright (C) 2005-2010 Free Software Foundation Europe e.V.
Copyright (C) 2018-2021 Bareos GmbH & Co. KG
Copyright (C) 2018-2022 Bareos GmbH & Co. KG

This program is Free Software; you can redistribute it and/or
modify it under the terms of version three of the GNU Affero General Public
Expand Down Expand Up @@ -68,9 +68,9 @@ class TlsOpenSslPrivate {
unsigned int max_psk_len);

/* each TCP connection has its own SSL_CTX object and SSL object */
SSL* openssl_;
SSL_CTX* openssl_ctx_;
SSL_CONF_CTX* openssl_conf_ctx_;
SSL* openssl_{};
SSL_CTX* openssl_ctx_{};
SSL_CONF_CTX* openssl_conf_ctx_{};

/* PskCredentials lookup map for all connections */
static std::map<const SSL_CTX*, PskCredentials> psk_client_credentials_;
Expand All @@ -84,18 +84,19 @@ class TlsOpenSslPrivate {
std::string protocol_;

/* cert attributes */
int tcp_file_descriptor_;
int tcp_file_descriptor_{};
std::string ca_certfile_;
std::string ca_certdir_;
std::string crlfile_;
std::string certfile_;
std::string keyfile_;
CRYPTO_PEM_PASSWD_CB* pem_callback_;
void* pem_userdata_;
CRYPTO_PEM_PASSWD_CB* pem_callback_{};
void* pem_userdata_{};
std::string dhfile_;
std::string cipherlist_;
bool verify_peer_;
/* *************** */
bool verify_peer_{};
std::shared_ptr<ConfigResourcesContainer>
config_table_{}; // config table being used
};

#endif // BAREOS_LIB_TLS_OPENSSL_PRIVATE_H_
41 changes: 22 additions & 19 deletions core/src/tests/test_config_parser_dir.cc
Expand Up @@ -100,28 +100,31 @@ TEST(ConfigParser_Dir, bareos_configparser_tests)
my_config->ParseConfig();
my_config->DumpResources(PrintMessage, NULL);

auto backup = my_config->BackupResourceTable();
my_config->ParseConfig();

me = (DirectorResource*)my_config->GetNextRes(R_DIRECTOR, nullptr);
my_config->own_resource_ = me;
ASSERT_NE(nullptr, me);
my_config->RestoreResourceTable(std::move(backup));
ASSERT_NE(nullptr, me);

// If a config already exists, BackupResourceTable() needs to be called before
// ParseConfig(), otherwise memory of the existing config is not freed
{
auto backup = my_config->BackupResourcesContainer();
my_config->ParseConfig();

me = (DirectorResource*)my_config->GetNextRes(R_DIRECTOR, nullptr);
my_config->own_resource_ = me;
ASSERT_NE(nullptr, me);
my_config->RestoreResourcesContainer(std::move(backup));
ASSERT_NE(nullptr, me);
}
// If a config already exists, BackupResourcesContainer() needs to be called
// before ParseConfig(), otherwise memory of the existing config is not freed
// completely
auto backup2 = my_config->BackupResourceTable();
my_config->ParseConfig();
{
auto backup = my_config->BackupResourcesContainer();
my_config->ParseConfig();

me = (DirectorResource*)my_config->GetNextRes(R_DIRECTOR, nullptr);
my_config->own_resource_ = me;
assert(me);
me = (DirectorResource*)my_config->GetNextRes(R_DIRECTOR, nullptr);
my_config->own_resource_ = me;
assert(me);

ASSERT_NE(nullptr, me);
my_config->DumpResources(PrintMessage, NULL);
ASSERT_NE(nullptr, me);
ASSERT_NE(nullptr, me);
my_config->DumpResources(PrintMessage, NULL);
ASSERT_NE(nullptr, me);
}
delete my_config;
}

Expand Down