8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-24 06:43:03 +01:00

Fixed CORE-5326: encrypting a database crashes host process when background encryption gets ready while no connection is established to that database

This commit is contained in:
AlexPeshkoff 2016-09-02 12:16:32 +03:00
parent 1bdd0bb0b6
commit 4156615d01
4 changed files with 61 additions and 5 deletions

View File

@ -403,6 +403,7 @@ const ULONG ATT_creator = 0x08000L; // This attachment created the DB
const ULONG ATT_monitor_done = 0x10000L; // Monitoring data is refreshed
const ULONG ATT_security_db = 0x20000L; // Attachment used for security purposes
const ULONG ATT_mapping = 0x40000L; // Attachment used for mapping auth block
const ULONG ATT_crypt_thread = 0x80000L; // Attachment from crypt thread
const ULONG ATT_NO_CLEANUP = (ATT_no_cleanup | ATT_notify_gc);

View File

@ -616,9 +616,14 @@ namespace Jrd {
lockAndReadHeader(tdbb, CRYPT_HDR_INIT);
}
void CryptoManager::terminateCryptThread(thread_db*)
void CryptoManager::terminateCryptThread(thread_db*, bool wait)
{
down = true;
if (wait && cryptThreadId)
{
Thread::waitForCompletion(cryptThreadId);
cryptThreadId = 0;
}
}
void CryptoManager::stopThreadUsing(thread_db* tdbb, Attachment* att)
@ -749,6 +754,11 @@ namespace Jrd {
writer.insertString(isc_dpb_user_name, "SYSDBA");
writer.insertByte(isc_dpb_no_db_triggers, TRUE);
// Avoid races with release_attachment() in jrd.cpp
MutexEnsureUnlock releaseGuard(cryptAttMutex, FB_FUNCTION);
releaseGuard.enter();
if (!down)
{
RefPtr<JAttachment> jAtt(REF_NO_INCR, dbb.dbb_provider->attachDatabase(&status_vector,
dbb.dbb_filename.c_str(), writer.getBufferLength(), writer.getBuffer()));
check(&status_vector);
@ -757,6 +767,9 @@ namespace Jrd {
Attachment* att = jAtt->getHandle();
if (!att)
Arg::Gds(isc_att_shutdown).raise();
att->att_flags |= ATT_crypt_thread;
releaseGuard.leave();
ThreadContextHolder tdbb(att->att_database, att, &status_vector);
tdbb->tdbb_quantum = SWEEP_QUANTUM;
@ -848,6 +861,7 @@ namespace Jrd {
{
writeDbHeader(tdbb, 0);
}
}
// Release exclusive lock on StartCryptThread
lckRelease = true;

View File

@ -41,6 +41,8 @@
#include "../jrd/status.h"
#include "firebird/Interface.h"
#define CRYPT_DEBUG(A)
// forward
class Config;
@ -278,7 +280,7 @@ public:
void detach(thread_db* tdbb, Attachment* att);
void startCryptThread(thread_db* tdbb);
void terminateCryptThread(thread_db* tdbb);
void terminateCryptThread(thread_db* tdbb, bool wait = false);
void stopThreadUsing(thread_db* tdbb, Attachment* att);
class IOCallback
@ -411,6 +413,9 @@ private:
SINT64 slowIO;
bool crypt, process, down, run;
public:
Firebird::Mutex cryptAttMutex;
};
} // namespace Jrd

View File

@ -6359,10 +6359,47 @@ static void release_attachment(thread_db* tdbb, Jrd::Attachment* attachment)
attachment->mergeStats();
// remove the attachment block from the dbb linked list
// avoid races with crypt thread
MutexEnsureUnlock cryptGuard(dbb->dbb_crypto_manager->cryptAttMutex, FB_FUNCTION);
cryptGuard.enter();
Sync sync(&dbb->dbb_sync, "jrd.cpp: release_attachment");
sync.lock(SYNC_EXCLUSIVE);
// stop the crypt thread if we release last regular attachment
Jrd::Attachment* crypt_att = NULL;
CRYPT_DEBUG(fprintf(stderr, "\nrelease attachment=%p\n", attachment));
for (Jrd::Attachment* att = dbb->dbb_attachments; att; att = att->att_next)
{
CRYPT_DEBUG(fprintf(stderr, "att=%p crypt_att=%p F=%c ", att, crypt_att, att->att_flags & ATT_crypt_thread ? '1' : '0'));
if (att == attachment)
{
CRYPT_DEBUG(fprintf(stderr, "self\n"));
continue;
}
if (att->att_flags & ATT_crypt_thread)
{
crypt_att = att;
CRYPT_DEBUG(fprintf(stderr, "found crypt_att=%p\n", crypt_att));
continue;
}
crypt_att = NULL;
CRYPT_DEBUG(fprintf(stderr, "other\n"));
break;
}
cryptGuard.leave();
if (crypt_att)
{
sync.unlock();
CRYPT_DEBUG(fprintf(stderr, "crypt_att=%p terminateCryptThread\n", crypt_att));
dbb->dbb_crypto_manager->terminateCryptThread(tdbb, true);
sync.lock(SYNC_EXCLUSIVE);
}
// remove the attachment block from the dbb linked list
for (Jrd::Attachment** ptr = &dbb->dbb_attachments; *ptr; ptr = &(*ptr)->att_next)
{
if (*ptr == attachment)
@ -6386,8 +6423,7 @@ static void release_attachment(thread_db* tdbb, Jrd::Attachment* attachment)
}
tdbb->setAttachment(NULL);
Jrd::Attachment::destroy(attachment); // string were re-saved in the beginning of this function,
// keep that in sync please
Jrd::Attachment::destroy(attachment);
}