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

Fix database merge crash when fdosecrets is enabled #10136

Merged
merged 3 commits into from
Jan 2, 2024

Conversation

jkloetzke
Copy link
Contributor

I ran into a crash when merging two databases where the source/alien database had a newer entry:

(gdb) bt
#0  0x000055555564a5ae in QScopedPointer<QObjectData, QScopedPointerDeleter<QObjectData> >::operator-> (this=0x8)
    at /usr/include/x86_64-linux-gnu/qt5/QtCore/qscopedpointer.h:118
#1  0x000055555565ca82 in QObject::parent (this=0x0) at /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject.h:425
#2  0x00005555558de6c2 in FdoSecrets::Item::collection (this=0x0) at /home/jkloetzke/src/keepassxc/src/fdosecrets/objects/Item.cpp:336
#3  0x00005555558b8818 in FdoSecrets::DBusMgr::emitItemCreated (this=0x555556866970, item=0x0)
    at /home/jkloetzke/src/keepassxc/src/fdosecrets/dbus/DBusMgr.cpp:540
#4  0x00005555558bdcf5 in QtPrivate::FunctorCall<QtPrivate::IndexesList<0>, QtPrivate::List<FdoSecrets::Item*>, void, void (FdoSecrets::DBusMgr::*)(FdoSecrets::Item*)>::call (
    f=(void (FdoSecrets::DBusMgr::*)(FdoSecrets::DBusMgr * const, FdoSecrets::Item *)) 0x5555558b87e0 <FdoSecrets::DBusMgr::emitItemCreated(FdoSecrets::Item*)>, o=0x555556866970, arg=0x7fffffffc190) at /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h:152
#5  0x00005555558bd764 in QtPrivate::FunctionPointer<void (FdoSecrets::DBusMgr::*)(FdoSecrets::Item*)>::call<QtPrivate::List<FdoSecrets::Item*>, void> (
    f=(void (FdoSecrets::DBusMgr::*)(FdoSecrets::DBusMgr * const, FdoSecrets::Item *)) 0x5555558b87e0 <FdoSecrets::DBusMgr::emitItemCreated(FdoSecrets::Item*)>, o=0x555556866970, arg=0x7fffffffc190) at /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h:185
#6  0x00005555558bcedd in QtPrivate::QSlotObject<void (FdoSecrets::DBusMgr::*)(FdoSecrets::Item*), QtPrivate::List<FdoSecrets::Item*>, void>::impl
    (which=1, this_=0x555557eebb40, r=0x555556866970, a=0x7fffffffc190, ret=0x0) at /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h:418
#7  0x00007ffff62e8f4f in ?? () from /lib/x86_64-linux-gnu/libQt5Core.so.5
#8  0x0000555555893832 in FdoSecrets::Collection::itemCreated (this=0x555557bf3840, _t1=0x0)
    at /home/jkloetzke/tmp/keepassxc/src/fdosecrets/fdosecrets_autogen/64PJ3GCGVF/moc_Collection.cpp:378
#9  0x00005555558d7504 in FdoSecrets::Collection::onEntryAdded (this=0x555557bf3840, entry=0x55555619d1c0, emitSignal=true)
    at /home/jkloetzke/src/keepassxc/src/fdosecrets/objects/Collection.cpp:517
#10 0x00005555558d7555 in operator() (__closure=0x555557cbd390, entry=0x55555619d1c0)
    at /home/jkloetzke/src/keepassxc/src/fdosecrets/objects/Collection.cpp:528
#11 0x00005555558d9bf3 in QtPrivate::FunctorCall<QtPrivate::IndexesList<0>, QtPrivate::List<Entry*>, void, FdoSecrets::Collection::connectGroupSignalRecursive(Group*)::<lambda(Entry*)> >::call(struct {...} &, void **) (f=..., arg=0x7fffffffc410)
    at /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h:146
#12 0x00005555558d9909 in QtPrivate::Functor<FdoSecrets::Collection::connectGroupSignalRecursive(Group*)::<lambda(Entry*)>, 1>::call<QtPrivate::List<Entry*>, void>(struct {...} &, void *, void **) (f=..., arg=0x7fffffffc410) at /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h:256
#13 0x00005555558d97b2 in QtPrivate::QFunctorSlotObject<FdoSecrets::Collection::connectGroupSignalRecursive(Group*)::<lambda(Entry*)>, 1, QtPrivate::List<Entry*>, void>::impl(int, QtPrivate::QSlotObjectBase *, QObject *, void **, bool *) (which=1, this_=0x555557cbd380, r=0x555557bf3840, 
    a=0x7fffffffc410, ret=0x0) at /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h:443
#14 0x00007ffff62e8f4f in ?? () from /lib/x86_64-linux-gnu/libQt5Core.so.5
#15 0x0000555555671078 in Group::entryAdded (this=0x5555571b6a90, _t1=0x55555619d1c0)
    at /home/jkloetzke/tmp/keepassxc/src/keepassx_core_autogen/TAC5DWH4SE/moc_Group.cpp:458
#16 0x00005555556b740a in Group::addEntry (this=0x5555571b6a90, entry=0x55555619d1c0) at /home/jkloetzke/src/keepassxc/src/core/Group.cpp:961
#17 0x000055555569eb9b in Entry::setGroup (this=0x55555619d1c0, group=0x5555571b6a90, trackPrevious=true)
    at /home/jkloetzke/src/keepassxc/src/core/Entry.cpp:1270
#18 0x000055555582c26b in Merger::moveEntry (this=0x7fffffffc980, entry=0x55555619d1c0, targetGroup=0x5555571b6a90)
    at /home/jkloetzke/src/keepassxc/src/core/Merger.cpp:186
#19 0x000055555582d190 in Merger::resolveEntryConflict_MergeHistories (this=0x7fffffffc980, context=..., sourceEntry=0x555556e4c7e0, 
    targetEntry=0x555556afe710, mergeMethod=Group::KeepNewer) at /home/jkloetzke/src/keepassxc/src/core/Merger.cpp:349
#20 0x000055555582d7e3 in Merger::resolveEntryConflict (this=0x7fffffffc980, context=..., sourceEntry=0x555556e4c7e0, targetEntry=0x555556afe710)
    at /home/jkloetzke/src/keepassxc/src/core/Merger.cpp:393
#21 0x000055555582b187 in Merger::mergeGroup (this=0x7fffffffc980, context=...) at /home/jkloetzke/src/keepassxc/src/core/Merger.cpp:96
#22 0x000055555582b83e in Merger::mergeGroup (this=0x7fffffffc980, context=...) at /home/jkloetzke/src/keepassxc/src/core/Merger.cpp:129
#23 0x000055555582ac17 in Merger::merge (this=0x7fffffffc980) at /home/jkloetzke/src/keepassxc/src/core/Merger.cpp:65
#24 0x00005555557465c7 in DatabaseWidget::mergeDatabase (this=0x555556959480, accepted=true)
    at /home/jkloetzke/src/keepassxc/src/gui/DatabaseWidget.cpp:1179

It turns out the fdosecrets feature is not happy that a second entry is briefly added to a group/database with the same UUID. This will cause the DBus registration to fail. Subsequently, the nullptr is not handled and leads to the crash above. If desired, I can also open a PR for the release/2.7.x branch where I developed the fix in the first place.

Screenshots

n/a

Testing strategy

Merged the databases that previously caused the crash

Type of change

  • ✅ Bug fix (non-breaking change that fixes an issue)

src/core/Merger.cpp Show resolved Hide resolved
src/core/Entry.cpp Show resolved Hide resolved
@droidmonkey
Copy link
Member

You also need to run make format

Adding the Entry to the Group will emit signals about the action.
Present the object with the correct parent already.
If an entry cannot be registered on DBus, Item::Create() will return a
nullptr. Basically, this can only happen if there is already an item
with the same UUID in the collection. The only viable option here is to
ignore the new entry.
If the alien database (source) entry is newer, a copy of the entry is
made. But before moving the merged entry to the target group, it must be
removed. Otherwise there will be briefly two entries with the same UUID
in the same group/database.

Even though this is only the case during the transaction, it can still
be observed because the operations emit signals. A notable problem is
the fdosecrets feature that relies on the uniqueness of the UUID or will
otherwise run into problems because the UUID is used as part of the DBus
path.
@droidmonkey droidmonkey merged commit a8cfefe into keepassxreboot:develop Jan 2, 2024
11 checks passed
@jkloetzke jkloetzke deleted the fix-merge-crash branch January 2, 2024 13:03
@droidmonkey droidmonkey added the pr: backported Pull request backported to previous release label Jan 30, 2024
droidmonkey added a commit that referenced this pull request Jan 30, 2024
* Entry: re-parent before adding to new group

Adding the Entry to the Group will emit signals about the action.
Present the object with the correct parent already.

* fdosecrets: Item::Create() can fail

If an entry cannot be registered on DBus, Item::Create() will return a
nullptr. Basically, this can only happen if there is already an item
with the same UUID in the collection. The only viable option here is to
ignore the new entry.

* Merger: prevent duplicate entry when merging histories

If the source entry is newer, a copy of the entry is made. But before
moving the merged entry to the target group, it must be removed.
Otherwise there will be briefly two entries with the same UUID
in the same group/database.

Even though this is only the case during the transaction, it can still
be observed because the operations emit signals. A notable problem is
the fdosecrets feature that relies on the uniqueness of the UUID or will
otherwise run into problems because the UUID is used as part of the DBus
path.
droidmonkey added a commit that referenced this pull request Feb 4, 2024
* Entry: re-parent before adding to new group

Adding the Entry to the Group will emit signals about the action.
Present the object with the correct parent already.

* fdosecrets: Item::Create() can fail

If an entry cannot be registered on DBus, Item::Create() will return a
nullptr. Basically, this can only happen if there is already an item
with the same UUID in the collection. The only viable option here is to
ignore the new entry.

* Merger: prevent duplicate entry when merging histories

If the source entry is newer, a copy of the entry is made. But before
moving the merged entry to the target group, it must be removed.
Otherwise there will be briefly two entries with the same UUID
in the same group/database.

Even though this is only the case during the transaction, it can still
be observed because the operations emit signals. A notable problem is
the fdosecrets feature that relies on the uniqueness of the UUID or will
otherwise run into problems because the UUID is used as part of the DBus
path.
libf-de pushed a commit to libf-de/keepassxc-secretservice-dbus that referenced this pull request Mar 11, 2024
Release 2.7.7

- Support USB Hotplug for Hardware Key interface [keepassxreboot#10092]
- Support 1PUX and Bitwarden import [keepassxreboot#9815]
- Browser: Add support for PassKeys [keepassxreboot#8825, keepassxreboot#9987, keepassxreboot#10318]
- Build System: Move to vcpkg manifest mode [keepassxreboot#10088]

- Fix multiple TOTP issues [keepassxreboot#9874]
- Fix focus loss on save when the editor is not visible anymore [keepassxreboot#10075]
- Fix visual when removing entry from history [keepassxreboot#9947]
- Fix first entry is not selected when a search is performed [keepassxreboot#9868]
- Prevent scrollbars on entry drag/drop [keepassxreboot#9747]
- Prevent duplicate characters in "Also choose from" field of password generator  [keepassxreboot#9803]
- Security: Prevent byte-by-byte and attachment inference side channel attacks [keepassxreboot#10266]
- Browser: Fix raising Update Entry messagebox [keepassxreboot#9853]
- Browser: Fix bugs when returning credentials [keepassxreboot#9136]
- Browser: Fix crash on database open from browser [keepassxreboot#9939]
- Browser: Fix support for referenced URL fields [keepassxreboot#8788]
- MacOS: Fix crash when changing highlight/accent color [keepassxreboot#10348]
- MacOS: Fix TouchID appearing even though lid is closed [keepassxreboot#10092]
- Windows: Fix terminating KeePassXC processes with MSI installer [keepassxreboot#9822]
- FdoSecrets: Fix database merge crash when enabled [keepassxreboot#10136]

# -----BEGIN PGP SIGNATURE-----
#
# iQEzBAABCAAdFiEENIkEDB8MPuq41ValRA/GXy4MbgEFAmXs7VsACgkQRA/GXy4M
# bgHLpwf/brnyPPs3gJxZmD2pn8542D4CCsDh0fTceurOtqCe3J4Y+Fftc5euuoQu
# 6rP4vJdd586l7JX5FnYIPXvGiU9op3MudJh+y+RN/PWwKcXNIXfUItMhpZEka49n
# xnw+Wvbilg1QIHSSmZdIjBpohnEkA67qhWauc3bCacrRyEvIOzVMTxnqDTe4GUDy
# CyauaRMMKezRTpLxSsk63TDAZZgDwK4ci5lC6ysHekc1Za6IbI3fMFjz1BGj+kPU
# tMHMfDCWqK/5JZ27ZWcxy7m8tJY9m3rb+MoCyFRQz9ixaEe29yf5NqYdm9sn1Dlh
# O7aFi7/EJtsBlXdguw5BcTPbsL7XEQ==
# =Cots
# -----END PGP SIGNATURE-----
# gpg: directory '/home/runner/.gnupg' created
# gpg: keybox '/home/runner/.gnupg/pubring.kbx' created
# gpg: Signature made Sat Mar  9 23:14:35 2024 UTC
# gpg:                using RSA key 3489040C1F0C3EEAB8D556A5440FC65F2E0C6E01
# gpg: Can't check signature: No public key
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
crash 💥 feature: Secret Service pr: backported Pull request backported to previous release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants