From cdae8ea4ef2a742c8181669e6d01663c4626b693 Mon Sep 17 00:00:00 2001 From: Felix Yan Date: Mon, 30 Mar 2026 17:07:56 +0800 Subject: [PATCH] fix: remove ti->disconnect() in entityAboutToDestroy handler to prevent UAF SIGSEGV When the greeter Wayland client disconnects (e.g. after login), wl_client_destroy destroys all client resources in an unspecified order. WSurface objects (focusedSurface / enabledSurface) backed by wl_surface resources are typically freed before the text_input_v2 resource. The WSurface C++ objects are destroyed and their memory reclaimed at that point. WInputMethodHelper::handleNewTI() connects a lambda to WTextInput::entityAboutToDestroy that called ti->disconnect(). QObject::disconnect(ti, ...) not only severs connections where ti is the sender, but also walks every receiver-side entry where ti is the receiver and removes the connection from the corresponding SENDER's ConnectionData. If a sender (e.g. focusedSurface) has already been freed, Qt dereferences its stale ConnectionData pointer and crashes in QObjectPrivate::ConnectionData::removeConnection (atomic fetch_sub on freed memory), observed as SIGSEGV in the coredump: #0 std::__atomic_base::fetch_sub (libQt6Core) #1 QObjectPrivate::ConnectionData::removeConnection #2 QMetaObjectPrivate::disconnectHelper #3 QMetaObjectPrivate::disconnect #4 QObject::disconnect #5 QtPrivate::QSlotObjectBase::call <- the lambda #6 tiv2::handle_text_input_resource_destroy #7 remove_and_destroy_resource ... #13 destroy_client_with_error Fix: remove ti->disconnect() from the lambda. The explicit bookkeeping that was needed (removeAll + disableTI) is kept. All remaining Qt signal connections are cleaned up automatically and safely by the QObject destructor that runs when delete text_input is called immediately after Q_EMIT entityAboutToDestroy() in handle_text_input_resource_destroy, by which point the wayland-server teardown for all other resources has completed. --- waylib/src/server/protocols/winputmethodhelper.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/waylib/src/server/protocols/winputmethodhelper.cpp b/waylib/src/server/protocols/winputmethodhelper.cpp index dea623dea..1b11c192e 100644 --- a/waylib/src/server/protocols/winputmethodhelper.cpp +++ b/waylib/src/server/protocols/winputmethodhelper.cpp @@ -348,7 +348,14 @@ void WInputMethodHelper::handleNewTI(WTextInput *ti) connect(ti, &WTextInput::entityAboutToDestroy, this, [this, d, ti]{ d->textInputs.removeAll(ti); disableTI(ti); - ti->disconnect(); + // Do NOT call ti->disconnect() here: it would attempt to access + // the ConnectionData of sender objects (e.g. WSurface focusedSurface / + // enabledSurface) that wl_client_destroy may already have freed before + // reaching the text-input resource, causing a UAF SIGSEGV in + // QObjectPrivate::ConnectionData::removeConnection (fetch_sub on freed + // memory). The QObject destructor invoked by delete text_input in + // handle_text_input_resource_destroy will clean up all connections + // safely once the sender objects have finished tearing down. }); // textInputs only save and traverse text inputs, do not handle connections // Whether this text input belongs to current seat or not, we should connect // its requestFocus signal for it might request focus from another seat to activate