mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-24 10: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:
parent
1bdd0bb0b6
commit
4156615d01
@ -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_monitor_done = 0x10000L; // Monitoring data is refreshed
|
||||||
const ULONG ATT_security_db = 0x20000L; // Attachment used for security purposes
|
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_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);
|
const ULONG ATT_NO_CLEANUP = (ATT_no_cleanup | ATT_notify_gc);
|
||||||
|
|
||||||
|
@ -616,9 +616,14 @@ namespace Jrd {
|
|||||||
lockAndReadHeader(tdbb, CRYPT_HDR_INIT);
|
lockAndReadHeader(tdbb, CRYPT_HDR_INIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CryptoManager::terminateCryptThread(thread_db*)
|
void CryptoManager::terminateCryptThread(thread_db*, bool wait)
|
||||||
{
|
{
|
||||||
down = true;
|
down = true;
|
||||||
|
if (wait && cryptThreadId)
|
||||||
|
{
|
||||||
|
Thread::waitForCompletion(cryptThreadId);
|
||||||
|
cryptThreadId = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CryptoManager::stopThreadUsing(thread_db* tdbb, Attachment* att)
|
void CryptoManager::stopThreadUsing(thread_db* tdbb, Attachment* att)
|
||||||
@ -749,6 +754,11 @@ namespace Jrd {
|
|||||||
writer.insertString(isc_dpb_user_name, "SYSDBA");
|
writer.insertString(isc_dpb_user_name, "SYSDBA");
|
||||||
writer.insertByte(isc_dpb_no_db_triggers, TRUE);
|
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,
|
RefPtr<JAttachment> jAtt(REF_NO_INCR, dbb.dbb_provider->attachDatabase(&status_vector,
|
||||||
dbb.dbb_filename.c_str(), writer.getBufferLength(), writer.getBuffer()));
|
dbb.dbb_filename.c_str(), writer.getBufferLength(), writer.getBuffer()));
|
||||||
check(&status_vector);
|
check(&status_vector);
|
||||||
@ -757,6 +767,9 @@ namespace Jrd {
|
|||||||
Attachment* att = jAtt->getHandle();
|
Attachment* att = jAtt->getHandle();
|
||||||
if (!att)
|
if (!att)
|
||||||
Arg::Gds(isc_att_shutdown).raise();
|
Arg::Gds(isc_att_shutdown).raise();
|
||||||
|
att->att_flags |= ATT_crypt_thread;
|
||||||
|
releaseGuard.leave();
|
||||||
|
|
||||||
ThreadContextHolder tdbb(att->att_database, att, &status_vector);
|
ThreadContextHolder tdbb(att->att_database, att, &status_vector);
|
||||||
tdbb->tdbb_quantum = SWEEP_QUANTUM;
|
tdbb->tdbb_quantum = SWEEP_QUANTUM;
|
||||||
|
|
||||||
@ -848,6 +861,7 @@ namespace Jrd {
|
|||||||
{
|
{
|
||||||
writeDbHeader(tdbb, 0);
|
writeDbHeader(tdbb, 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Release exclusive lock on StartCryptThread
|
// Release exclusive lock on StartCryptThread
|
||||||
lckRelease = true;
|
lckRelease = true;
|
||||||
|
@ -41,6 +41,8 @@
|
|||||||
#include "../jrd/status.h"
|
#include "../jrd/status.h"
|
||||||
#include "firebird/Interface.h"
|
#include "firebird/Interface.h"
|
||||||
|
|
||||||
|
#define CRYPT_DEBUG(A)
|
||||||
|
|
||||||
// forward
|
// forward
|
||||||
|
|
||||||
class Config;
|
class Config;
|
||||||
@ -278,7 +280,7 @@ public:
|
|||||||
void detach(thread_db* tdbb, Attachment* att);
|
void detach(thread_db* tdbb, Attachment* att);
|
||||||
|
|
||||||
void startCryptThread(thread_db* tdbb);
|
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);
|
void stopThreadUsing(thread_db* tdbb, Attachment* att);
|
||||||
|
|
||||||
class IOCallback
|
class IOCallback
|
||||||
@ -411,6 +413,9 @@ private:
|
|||||||
|
|
||||||
SINT64 slowIO;
|
SINT64 slowIO;
|
||||||
bool crypt, process, down, run;
|
bool crypt, process, down, run;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Firebird::Mutex cryptAttMutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Jrd
|
} // namespace Jrd
|
||||||
|
@ -6359,10 +6359,47 @@ static void release_attachment(thread_db* tdbb, Jrd::Attachment* attachment)
|
|||||||
|
|
||||||
attachment->mergeStats();
|
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 sync(&dbb->dbb_sync, "jrd.cpp: release_attachment");
|
||||||
sync.lock(SYNC_EXCLUSIVE);
|
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)
|
for (Jrd::Attachment** ptr = &dbb->dbb_attachments; *ptr; ptr = &(*ptr)->att_next)
|
||||||
{
|
{
|
||||||
if (*ptr == attachment)
|
if (*ptr == attachment)
|
||||||
@ -6386,8 +6423,7 @@ static void release_attachment(thread_db* tdbb, Jrd::Attachment* attachment)
|
|||||||
}
|
}
|
||||||
|
|
||||||
tdbb->setAttachment(NULL);
|
tdbb->setAttachment(NULL);
|
||||||
Jrd::Attachment::destroy(attachment); // string were re-saved in the beginning of this function,
|
Jrd::Attachment::destroy(attachment);
|
||||||
// keep that in sync please
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user