-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Segmentation fault on exiting keepassxc-cli after DB was opened #5367
Description
Overview
After opening a database file with the keepassxc-cli,
entering a valid command and exiting the cli a seg-fault occurs.
Steps to Reproduce
- Open a .kdbx database file with the keepassxc-cli open cmd
- Enter any valid command as defined in the namespace commands
- Exit the shell by either "exit" or "quit"
-> boom, segmentation fault.
After investigating with AddressSanitizer it seems that
the ~Database destructor is called twice, since the QSharedPointer
variable cmd->currentDatabase & currentDatabase is initialized to
the the same address.
seen in:
https://github.com/keepassxreboot/keepassxc/blob/develop/src/cli/keepassxc-cli.cpp#L167#L169
Expected Behavior
No call to destructor of currentDatabase variable twice.
Actual Behavior
Segmentation fault due to double-free.
Context
KeePassXC - Version 2.6.1-snapshot
Build Type: Snapshot
Revision: f49f62d
Qt 5.15.0
Debugging mode is enabled.
Operating system: Arch Linux
CPU architecture: x86_64
Kernel: linux 5.8.5-arch1-1
Enabled extensions:
- Auto-Type
- Browser Integration
- SSH Agent
- KeeShare (signed and unsigned sharing)
- YubiKey
- Secret Service Integration
Cryptographic libraries:
libgcrypt 1.8.6
AddressSanitizer Debug-output:
./keepassxc-cli open ~/Passwords.kdbx
Enter password to unlock /home/ExampleUser/Passwords.kdbx:
Passwords> ls
internet/
Passwords> exit
=================================================================
==57198==ERROR: AddressSanitizer: heap-use-after-free on address 0x60400000b9e4 at pc 0x56517f75b886 bp 0x7ffd6a6c1190 sp 0x7ffd6a6c1180
READ of size 4 at 0x60400000b9e4 thread T0
#0 0x56517f75b885 in QHash<QUuid, QPointer<Database> >::isEmpty() const (/home/ExampleUser/Code/keepassxc/build/src/cli/keepassxc-cli+0x5f6885)
#1 0x56517f758525 in QHash<QUuid, QPointer<Database> >::remove(QUuid const&) (/home/ExampleUser/Code/keepassxc/build/src/cli/keepassxc-cli+0x5f3525)
#2 0x56517f750a96 in Database::releaseData() /home/ExampleUser/Code/keepassxc/src/core/Database.cpp:436
#3 0x56517f74d9c6 in Database::~Database() /home/ExampleUser/Code/keepassxc/src/core/Database.cpp:75
#4 0x56517f6b7f5b in QtSharedPointer::ExternalRefCountWithContiguousData<Database>::deleter(QtSharedPointer::ExternalRefCountData*) /usr/include/qt/QtCore/qsharedpointer_impl.h:247
#5 0x56517f68c40f in QtSharedPointer::ExternalRefCountData::destroy() /usr/include/qt/QtCore/qsharedpointer_impl.h:148
#6 0x56517f68e8f6 in QSharedPointer<Database>::deref(QtSharedPointer::ExternalRefCountData*) /usr/include/qt/QtCore/qsharedpointer_impl.h:456
#7 0x56517f68e14e in QSharedPointer<Database>::deref() /usr/include/qt/QtCore/qsharedpointer_impl.h:451
#8 0x56517f68d16f in QSharedPointer<Database>::~QSharedPointer() /usr/include/qt/QtCore/qsharedpointer_impl.h:309
#9 0x56517f68fe82 in Command::~Command() /home/ExampleUser/Code/keepassxc/src/cli/Command.cpp:108
#10 0x56517f68f45a in DatabaseCommand::~DatabaseCommand() /home/ExampleUser/Code/keepassxc/src/cli/DatabaseCommand.h:27
#11 0x56517f6b3d54 in List::~List() /home/ExampleUser/Code/keepassxc/src/cli/List.h:23
#12 0x56517f6b3d6f in List::~List() /home/ExampleUser/Code/keepassxc/src/cli/List.h:23
#13 0x56517f6a0062 in QtSharedPointer::CustomDeleter<List, QtSharedPointer::NormalDeleter>::execute() (/home/ExampleUser/Code/keepassxc/build/src/cli/keepassxc-cli+0x53b062)
#14 0x56517f69dd09 in QtSharedPointer::ExternalRefCountWithCustomDeleter<List, QtSharedPointer::NormalDeleter>::deleter(QtSharedPointer::ExternalRefCountData*) /usr/include/qt/QtCore/qsharedpointer_impl.h:204
#15 0x56517f68c40f in QtSharedPointer::ExternalRefCountData::destroy() /usr/include/qt/QtCore/qsharedpointer_impl.h:148
#16 0x56517f68e9e2 in QSharedPointer<Command>::deref(QtSharedPointer::ExternalRefCountData*) /usr/include/qt/QtCore/qsharedpointer_impl.h:456
#17 0x56517f68e238 in QSharedPointer<Command>::deref() /usr/include/qt/QtCore/qsharedpointer_impl.h:451
#18 0x56517f68d293 in QSharedPointer<Command>::~QSharedPointer() /usr/include/qt/QtCore/qsharedpointer_impl.h:309
#19 0x56517f6a09b7 in std::enable_if<QTypeInfo<QSharedPointer<Command> >::isComplex, void>::type QMapNodeBase::callDestructorIfNecessary<QSharedPointer<Command> >(QSharedPointer<Command>&) (/home/ExampleUser/Code/keepassxc/build/src/cli/keepassxc-cli+0x53b9b7)
#20 0x56517f69f3d9 in QMapNode<QString, QSharedPointer<Command> >::destroySubTree() (/home/ExampleUser/Code/keepassxc/build/src/cli/keepassxc-cli+0x53a3d9)
#21 0x56517f6a0a0d in QMapNode<QString, QSharedPointer<Command> >::doDestroySubTree(std::integral_constant<bool, true>) (/home/ExampleUser/Code/keepassxc/build/src/cli/keepassxc-cli+0x53ba0d)
#22 0x56517f69f3e5 in QMapNode<QString, QSharedPointer<Command> >::destroySubTree() (/home/ExampleUser/Code/keepassxc/build/src/cli/keepassxc-cli+0x53a3e5)
#23 0x56517f6a0a0d in QMapNode<QString, QSharedPointer<Command> >::doDestroySubTree(std::integral_constant<bool, true>) (/home/ExampleUser/Code/keepassxc/build/src/cli/keepassxc-cli+0x53ba0d)
#24 0x56517f69f3e5 in QMapNode<QString, QSharedPointer<Command> >::destroySubTree() (/home/ExampleUser/Code/keepassxc/build/src/cli/keepassxc-cli+0x53a3e5)
#25 0x56517f6a0a53 in QMapNode<QString, QSharedPointer<Command> >::doDestroySubTree(std::integral_constant<bool, true>) (/home/ExampleUser/Code/keepassxc/build/src/cli/keepassxc-cli+0x53ba53)
#26 0x56517f69f3e5 in QMapNode<QString, QSharedPointer<Command> >::destroySubTree() (/home/ExampleUser/Code/keepassxc/build/src/cli/keepassxc-cli+0x53a3e5)
#27 0x56517f6a0a53 in QMapNode<QString, QSharedPointer<Command> >::doDestroySubTree(std::integral_constant<bool, true>) (/home/ExampleUser/Code/keepassxc/build/src/cli/keepassxc-cli+0x53ba53)
#28 0x56517f69f3e5 in QMapNode<QString, QSharedPointer<Command> >::destroySubTree() (/home/ExampleUser/Code/keepassxc/build/src/cli/keepassxc-cli+0x53a3e5)
#29 0x56517f69c74b in QMapData<QString, QSharedPointer<Command> >::destroy() (/home/ExampleUser/Code/keepassxc/build/src/cli/keepassxc-cli+0x53774b)
#30 0x56517f698cba in QMap<QString, QSharedPointer<Command> >::~QMap() (/home/ExampleUser/Code/keepassxc/build/src/cli/keepassxc-cli+0x533cba)
#31 0x7ff6b7ad8db6 in __run_exit_handlers (/usr/lib/libc.so.6+0x3fdb6)
#32 0x7ff6b7ad8f5d in __GI_exit (/usr/lib/libc.so.6+0x3ff5d)
#33 0x7ff6b7ac1158 in __libc_start_main (/usr/lib/libc.so.6+0x28158)
#34 0x56517f68846d in _start (/home/ExampleUser/Code/keepassxc/build/src/cli/keepassxc-cli+0x52346d)
0x60400000b9e4 is located 20 bytes inside of 48-byte region [0x60400000b9d0,0x60400000ba00)
freed by thread T0 here:
#0 0x7ff6b98e0009 in operator delete(void*, unsigned long) /build/gcc/src/gcc/libsanitizer/asan/asan_new_delete.cpp:172
#1 0x56517f75dc58 in QHash<QUuid, QPointer<Database> >::freeData(QHashData*) (/home/ExampleUser/Code/keepassxc/build/src/cli/keepassxc-cli+0x5f8c58)
#2 0x56517f760205 in QHash<QUuid, QPointer<Database> >::~QHash() (/home/ExampleUser/Code/keepassxc/build/src/cli/keepassxc-cli+0x5fb205)
#3 0x7ff6b7ad8db6 in __run_exit_handlers (/usr/lib/libc.so.6+0x3fdb6)
previously allocated by thread T0 here:
#0 0x7ff6b98def41 in operator new(unsigned long) /build/gcc/src/gcc/libsanitizer/asan/asan_new_delete.cpp:99
#1 0x7ff6b81cfd47 in QHashData::detach_helper(void (*)(QHashData::Node*, void*), void (*)(QHashData::Node*), int, int) (/usr/lib/libQt5Core.so.5+0x107d47)
SUMMARY: AddressSanitizer: heap-use-after-free (/home/ExampleUser/Code/keepassxc/build/src/cli/keepassxc-cli+0x5f6885) in QHash<QUuid, QPointer<Database> >::isEmpty() const
Shadow bytes around the buggy address:
0x0c087fff96e0: fa fa fd fd fd fd fd fd fa fa 00 00 00 00 00 fa
0x0c087fff96f0: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 fa
0x0c087fff9700: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 fa
0x0c087fff9710: fa fa 00 00 00 00 00 fa fa fa fd fd fd fd fd fa
0x0c087fff9720: fa fa fd fd fd fd fd fa fa fa 00 00 00 00 00 fa
=>0x0c087fff9730: fa fa fd fd fd fd fd fd fa fa fd fd[fd]fd fd fd
0x0c087fff9740: fa fa fd fd fd fd fd fd fa fa 00 00 00 00 00 fa
0x0c087fff9750: fa fa fd fd fd fd fd fd fa fa fd fd fd fd fd fa
0x0c087fff9760: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fd
0x0c087fff9770: fa fa fd fd fd fd fd fd fa fa fd fd fd fd fd fd
0x0c087fff9780: fa fa fd fd fd fd fd fd fa fa fd fd fd fd fd fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==57198==ABORTING