add minimal reproducer for qtbase wayland screen use-after-free
This commit is contained in:
parent
92afaa7f32
commit
b05861de78
4 changed files with 120 additions and 0 deletions
63
test/screen-uaf-reproducer/main.cpp
Normal file
63
test/screen-uaf-reproducer/main.cpp
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
// Minimal reproducer for Qt 6 Wayland screen use-after-free.
|
||||
//
|
||||
// Bug: libwayland resolves wl_output proxy pointers at demarshal time (when
|
||||
// events are read from the socket). If wl_registry.global_remove and
|
||||
// wl_surface.enter/leave for the same output arrive in the same dispatch
|
||||
// batch, the surface event handler receives a dangling proxy pointer.
|
||||
// QWaylandScreen::fromWlOutput() reads stale userdata from the freed proxy
|
||||
// and returns a garbage QWaylandScreen*, which crashes on dereference.
|
||||
//
|
||||
// Build:
|
||||
// cmake -B build && cmake --build build
|
||||
//
|
||||
// Run (on any wlroots-based compositor or Niri):
|
||||
// ./build/screen-uaf-reproducer &
|
||||
// # then toggle an output off/on rapidly, e.g.:
|
||||
// # wlr-randr --output eDP-1 --off && wlr-randr --output eDP-1 --on
|
||||
// # niri msg action power-off-monitors (then move mouse to wake)
|
||||
// # or just unplug/replug an external monitor
|
||||
//
|
||||
// The crash typically occurs within seconds of the output toggle.
|
||||
// Creating many surfaces increases the odds that a surface.leave event
|
||||
// lands in the same batch as the global_remove.
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QScreen>
|
||||
#include <QWindow>
|
||||
#include <QTimer>
|
||||
#include <vector>
|
||||
#include <cstdio>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
// Many surfaces = higher chance of batched enter/leave events
|
||||
constexpr int kWindows = 20;
|
||||
std::vector<std::unique_ptr<QWindow>> windows;
|
||||
windows.reserve(kWindows);
|
||||
|
||||
for (int i = 0; i < kWindows; ++i) {
|
||||
auto w = std::make_unique<QWindow>();
|
||||
w->setTitle(QStringLiteral("uaf-%1").arg(i));
|
||||
w->resize(1, 1);
|
||||
w->setFlag(Qt::ToolTip); // small, no decoration, no focus
|
||||
w->show();
|
||||
windows.push_back(std::move(w));
|
||||
}
|
||||
|
||||
std::fprintf(stderr,
|
||||
"screen-uaf-reproducer: %d surfaces created on %d screen(s).\n"
|
||||
"Toggle an output off/on to trigger the crash.\n",
|
||||
kWindows, QGuiApplication::screens().size());
|
||||
|
||||
// Log screen changes so we know when the toggle happens
|
||||
QObject::connect(&app, &QGuiApplication::screenAdded, [](QScreen *s) {
|
||||
std::fprintf(stderr, " screenAdded: %s\n", qPrintable(s->name()));
|
||||
});
|
||||
QObject::connect(&app, &QGuiApplication::screenRemoved, [](QScreen *s) {
|
||||
std::fprintf(stderr, " screenRemoved: %s\n", qPrintable(s->name()));
|
||||
});
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue