Bug#857264: plasma-workspace: xembedsniproxy often segfaults
Control: forward -1 https://bugs.kde.org/show_bug.cgi?id=359664
Control: tags -1 upstream fixed-upstream
Control: fixed -1 plasma-workspace/4:5.12.0-2
Dear Maintainer, hello Michael Meier,
from the segfault line I would suspect that this
crash happened in sniproxy.cpp, line 273.
There image may contain NULL that gets unconditionally
dereferenced.
Upstream would have fixed it in [1], contained first in 5.12.
Also applied in branch 5.8 [2], contained first in 5.8.9.
Upstream bug report would be [3].
This bug may still show up in current stretch version.
Kind regards,
Bernhard
[1] https://cgit.kde.org/plasma-workspace.git/commit/?id=e2b7c395ecdb660b7bec960f3c938fba175ca4f8
[2] https://cgit.kde.org/plasma-workspace.git/commit/?h=Plasma/5.8&id=12e3568042fb365aad3eccf2fefa58bbeb065210
[3] https://bugs.kde.org/show_bug.cgi?id=359664
-------
0x000055555556022d <+109>: callq 0x555555559bf0 <xcb_image_get@plt>
0x0000555555560256 <+150>: mov %rax,%rbx
271
272 // Don't hook up cleanup yet, we may use a different QImage after all
273 QImage naiveConversion = QImage(image->data, image->width, image->height, QImage::Format_ARGB32);
0x0000555555560232 <+114>: movzwl 0x2(%rax),%ecx <<<<<<<<<<<<
0x0000555555560236 <+118>: movzwl (%rax),%edx
-------
259 QImage SNIProxy::getImageNonComposite() const
260 {
...
270 xcb_image_t *image = xcb_image_get(c, m_windowId, 0, 0, geom->width, geom->height, 0xFFFFFFFF, XCB_IMAGE_FORMAT_Z_PIXMAP);
271
272 // Don't hook up cleanup yet, we may use a different QImage after all
273 QImage naiveConversion = QImage(image->data, image->width, image->height, QImage::Format_ARGB32);
# Jessie amd64 qemu VM
apt update
apt dist-upgrade
approx:
debian-9-stretch-snapshot.debian.org https://snapshot.debian.org/archive/debian/20170310T000000Z/
debian-9-stretch-debug-snapshot.debian.org https://snapshot.debian.org/archive/debian-debug/20170310T000000Z/
sources.list:
# snapshot
deb [check-valid-until=no] http://192.168.178.25:9999/debian-9-stretch-snapshot.debian.org/ stretch main
deb-src [check-valid-until=no] http://192.168.178.25:9999/debian-9-stretch-snapshot.debian.org/ stretch main
deb [check-valid-until=no] http://192.168.178.25:9999/debian-9-stretch-debug-snapshot.debian.org/ stretch-debug main
apt-get -o Acquire::Check-Valid-Until=false -o Acquire::Languages=none update
apt dist-upgrade
reboot
apt install xserver-xorg sddm kde-plasma-desktop binutils gdb elfutils plasma-workspace-dbgsym
apt install dpkg-dev devscripts
mkdir source/plasma-workspace/orig -p
cd source/plasma-workspace/orig
apt source plasma-workspace
cd
benutzer@debian:~$ dpkg -l | grep plasma-workspace
ii plasma-workspace 4:5.8.4-1 amd64 Plasma Workspace for KF5
ii plasma-workspace-dbgsym 4:5.8.4-1 amd64 Debug symbols for plasma-workspace
##############
From https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=857264:
[ 49.752174] xembedsniproxy[5458]: segfault at 2 ip 0000561b56ae2232 sp 00007ffffb32c330 error 4 in xembedsniproxy[561b56ad6000+14000]
https://www.enodev.fr/posts/decode-segfault-errors-in-dmesg.html
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/x86/mm/fault.c?h=linux-4.9.y#n31
------
/*
* Page fault error code bits:
*
* bit 0 == 0: no page found 1: protection fault
* bit 1 == 0: read access 1: write access
* bit 2 == 0: kernel-mode access 1: user-mode access
* bit 3 == 1: use of reserved bit detected
* bit 4 == 1: fault was an instruction fetch
* bit 5 == 1: protection keys block access
*/
enum x86_pf_error_code {
PF_PROT = 1 << 0,
PF_WRITE = 1 << 1,
PF_USER = 1 << 2,
PF_RSVD = 1 << 3,
PF_INSTR = 1 << 4,
PF_PK = 1 << 5,
};
"error 4" == 0b100
bit 0 == 0: no page found
bit 1 == 0: read access
bit 2 == 1: user-mode access
------
# Create a 'unstripped' binary
benutzer@debian:~$ gdb -q -ex quit --args /usr/bin/xembedsniproxy
Reading symbols from /usr/bin/xembedsniproxy...Reading symbols from /usr/lib/debug/.build-id/78/036ce04f32f09dd53a566ea3e172453fd64037.debug...done.
done.
cp -a /usr/bin/xembedsniproxy /tmp/xembedsniproxy
cp -a /usr/lib/debug/.build-id/78/036ce04f32f09dd53a566ea3e172453fd64037.debug /tmp/036ce04f32f09dd53a566ea3e172453fd64037.debug
eu-unstrip /tmp/xembedsniproxy /tmp/036ce04f32f09dd53a566ea3e172453fd64037.debug
benutzer@debian:~$ objdump --disassemble /tmp/036ce04f32f09dd53a566ea3e172453fd64037.debug | grep -E "232:|^00000" | grep "232:" -B1
00000000000071a0 <_ZN17QtMetaTypePrivate23QMetaTypeFunctionHelperI18KDbusToolTipStructLb1EE8DestructEPv>:
7232: ba 08 00 00 00 mov $0x8,%edx
--
0000000000008230 <_ZN19FdoSelectionManager18compositingChangedEv>:
8232: 55 push %rbp
--
000000000000c1c0 <_ZNK8SNIProxy20getImageNonCompositeEv>:
c232: 0f b7 48 02 movzwl 0x2(%rax),%ecx
--
000000000000d220 <_ZNK25StatusNotifierItemAdaptor2idEv>:
d232: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
--
000000000000e0a0 <_ZN36OrgKdeStatusNotifierWatcherInterface18qt_static_metacallEP7QObjectN11QMetaObject4CallEiPPv>:
e232: 83 f8 01 cmp $0x1,%eax
-> _ZNK8SNIProxy20getImageNonCompositeEv looks most promising -> read at offset 0x2 matches
------
gdb -q \
-ex 'set width 0' \
-ex 'set pagination off' \
-ex 'directory /home/benutzer/source/plasma-workspace/orig/plasma-workspace-5.8.4' \
-ex 'break main' \
-ex 'run' \
-ex 'dele 1' \
--args /usr/bin/xembedsniproxy
benutzer@debian:~$ gdb -q \
> -ex 'set width 0' \
> -ex 'set pagination off' \
> -ex 'directory /home/benutzer/source/plasma-workspace/orig/plasma-workspace-5.8.4' \
> -ex 'break main' \
> -ex 'run' \
> -ex 'dele 1' \
> --args /usr/bin/xembedsniproxy
Reading symbols from /usr/bin/xembedsniproxy...Reading symbols from /usr/lib/debug/.build-id/78/036ce04f32f09dd53a566ea3e172453fd64037.debug...done.
done.
Source directories searched: /home/benutzer/source/plasma-workspace/orig/plasma-workspace-5.8.4:$cdir:$cwd
Breakpoint 1 at 0x6790: file ./xembed-sni-proxy/main.cpp, line 39.
Starting program: /usr/bin/xembedsniproxy
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 1, main (argc=1, argv=0x7fffffffe688) at ./xembed-sni-proxy/main.cpp:39
39 {
(gdb) break _ZNK8SNIProxy20getImageNonCompositeEv
Breakpoint 2 at 0x5555555601c0: file ./xembed-sni-proxy/sniproxy.cpp, line 260.
(gdb) info b
Num Type Disp Enb Address What
2 breakpoint keep y 0x00005555555601c0 in SNIProxy::getImageNonComposite() const at ./xembed-sni-proxy/sniproxy.cpp:260
(gdb) disassemble /m _ZNK8SNIProxy20getImageNonCompositeEv
Dump of assembler code for function SNIProxy::getImageNonComposite() const:
260 {
...
270 xcb_image_t *image = xcb_image_get(c, m_windowId, 0, 0, geom->width, geom->height, 0xFFFFFFFF, XCB_IMAGE_FORMAT_Z_PIXMAP);
0x0000555555560212 <+82>: movzwl 0x12(%rax),%r9d
0x0000555555560217 <+87>: movzwl 0x10(%rax),%r8d
0x000055555556021c <+92>: xor %ecx,%ecx
0x000055555556021e <+94>: mov 0x18(%rbp),%esi
0x0000555555560221 <+97>: pushq $0x2
0x0000555555560223 <+99>: xor %edx,%edx
0x0000555555560225 <+101>: pushq $0xffffffffffffffff
0x0000555555560227 <+103>: mov %rbx,%rdi
0x000055555556022a <+106>: mov %rax,%r12
0x000055555556022d <+109>: callq 0x555555559bf0 <xcb_image_get@plt>
0x0000555555560256 <+150>: mov %rax,%rbx
271
272 // Don't hook up cleanup yet, we may use a different QImage after all
273 QImage naiveConversion = QImage(image->data, image->width, image->height, QImage::Format_ARGB32);
0x0000555555560232 <+114>: movzwl 0x2(%rax),%ecx <<<<<<<<<<<<
0x0000555555560236 <+118>: movzwl (%rax),%edx
0x0000555555560239 <+121>: lea 0x50(%rsp),%r14
0x000055555556023e <+126>: mov 0x28(%rax),%rsi
0x0000555555560242 <+130>: xor %r9d,%r9d
0x0000555555560245 <+133>: mov $0x5,%r8d
0x000055555556024b <+139>: mov %r14,%rdi
0x000055555556024e <+142>: movq $0x0,(%rsp)
0x0000555555560259 <+153>: callq 0x555555559c30 <_ZN6QImageC1EPhiiNS_6FormatEPFvPvES2_@plt>
0x0000555555560297 <+215>: mov %r14,%rdi
0x000055555556029a <+218>: callq 0x555555559f80 <_ZN6QImageD1Ev@plt>
274
275 if (isTransparentImage(naiveConversion)) {
...
End of assembler dump.
(gdb) list SNIProxy::getImageNonComposite
258
259 QImage SNIProxy::getImageNonComposite() const
260 {
261 auto c = QX11Info::connection();
262 auto cookie = xcb_get_geometry(c, m_windowId);
263 QScopedPointer<xcb_get_geometry_reply_t, QScopedPointerPodDeleter>
264 geom(xcb_get_geometry_reply(c, cookie, Q_NULLPTR));
265
266 if (!geom) {
267 return QImage();
268 }
269
270 xcb_image_t *image = xcb_image_get(c, m_windowId, 0, 0, geom->width, geom->height, 0xFFFFFFFF, XCB_IMAGE_FORMAT_Z_PIXMAP);
271
272 // Don't hook up cleanup yet, we may use a different QImage after all
273 QImage naiveConversion = QImage(image->data, image->width, image->height, QImage::Format_ARGB32);
274
275 if (isTransparentImage(naiveConversion)) {
276 QImage elaborateConversion = QImage(convertFromNative(image));
277
278 // Update icon only if it is at least partially opaque.
279 // This is just a workaround for X11 bug: xembed icon may suddenly
280 // become transparent for a one or few frames. Reproducible at least
281 // with WINE applications.
282 if (isTransparentImage(elaborateConversion)) {
283 qCDebug(SNIPROXY) << "Skip transparent xembed icon for" << m_windowId << Title();
284 return QImage();
285 } else
286 return elaborateConversion;
287 } else {
288 // Now we are sure we can eventually delete the xcb_image_t with this version
289 return QImage(image->data, image->width, image->height, image->stride, QImage::Format_ARGB32, sni_cleanup_xcb_image, image);
290 }
291 }
... I knew that I have seen this already ...
https://bugs.kde.org/show_bug.cgi?id=359664
Branch master, seems v5.12.0 was the first release containing it:
https://cgit.kde.org/plasma-workspace.git/commit/?id=e2b7c395ecdb660b7bec960f3c938fba175ca4f8
Branch 5.8, Tag v5.8.9 contains it:
https://cgit.kde.org/plasma-workspace.git/commit/?h=Plasma/5.8&id=12e3568042fb365aad3eccf2fefa58bbeb065210
Reply to: