Bug 480008

Summary: std::bad_alloc: integer overflow in screenGeometry() via qdbus plasma scripting
Product: [Plasma] plasmashell Reporter: Benjamin Flesch <benjaminflesch>
Component: generalAssignee: Plasma Bugs List <plasma-bugs>
Status: CONFIRMED ---    
Severity: crash CC: kde, nate, security
Priority: NOR    
Version: 5.27.10   
Target Milestone: 1.0   
Platform: Arch Linux   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:

Description Benjamin Flesch 2024-01-18 18:37:18 UTC
SUMMARY
***
screenGeometry() function available in plasma scripting language allows integer overflow

IMO this allows for exploitation, but only attack vector I can think of is a malware kde plasma theme (and even in this case you can run shellscripts via QML already). plasmashell runs on userid 1000 so impact of exploitation via qdbus also not really big.
***


STEPS TO REPRODUCE
short way:
1. open console and run the following command
2. qdbus org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript $(perl -E 'say "print(\"start\");while(true){print(\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\");screenGeometry(" . ('9' x 120000) . ")}"')
2. wait 5 minutes for plasmashell to crash with std::bad_alloc

long way:
1. journalctl -xe
2. send different commands via qdbus to the plasma scripting engine:
3. no error for screenGeometry(9):  `qdbus org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript $(perl -E 'say "print(JSON.stringify(screenGeometry(" . (9 x 1) . ")))"')` -> journalctl will print "requesting unexisting screen geometry 9"
4. integer overflow for screenGeometry(999999999999999): `qdbus org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript $(perl -E 'say "print(JSON.stringify(screenGeometry(" . (9 x 15) . ")))"')` -> journalctl will print "requesting unexisting screen geometry -1530494977"
5. integer overflow for screenGeometry(9x25): `qdbus org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript $(perl -E 'say "print(JSON.stringify(screenGeometry(" . (9 x 15) . ")))"')` -> journalctl will print "requesting unexisting screen geometry -2147483648"
6. integer overflow for screenGeometry(9x800) BUT NO MORE LOG MESSAGES  `qdbus org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript $(perl -E 'say "print(JSON.stringify(screenGeometry(" . (9 x 30) . ")))"')` -> journalctl will not print anything
7.  integer of length 120000 is the maximum you can send before qdbus complains about argument length: qdbus org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript $(perl -E 'say "print(JSON.stringify(screenGeometry(" . ('7' x 120000) . ")))"')


OBSERVED RESULT

journalctl:
requesting unexisting screen geometry 99999
requesting unexisting screen geometry 999999
requesting unexisting screen geometry 9999999
requesting unexisting screen geometry 999999999
requesting unexisting screen geometry -1530494977
<NO MORE LOGS>

terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
KCrash: Attempting to start /usr/bin/plasmashell
25 -- exe=/usr/bin/plasmashell
17 -- platform=wayland
20 -- appname=plasmashell
17 -- apppath=/usr/bin
9 -- signal=6
11 -- pid=125085
19 -- appversion=5.27.10
19 -- programname=Plasma
31 -- bugaddress=submit@bugs.kde.org
15 -- restarted=true
KCrash: crashing... crashRecursionCounter = 2
KCrash: Application Name = plasmashell path = /usr/bin pid = 125085
KCrash: Arguments: /usr/bin/plasmashell --replace 


(gdb) f
#0  __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=11, no_tid=no_tid@entry=0) at pthread_kill.c:44
44            return INTERNAL_SYSCALL_ERROR_P (ret) ? INTERNAL_SYSCALL_ERRNO (ret) : 0;
(gdb) do
Bottom (innermost) frame selected; you cannot go down.
(gdb) bt
#0  __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=11, no_tid=no_tid@entry=0) at pthread_kill.c:44
#1  0x000071cfbacac8a3 in __pthread_kill_internal (signo=11, threadid=<optimized out>) at pthread_kill.c:78
#2  0x000071cfbac5c668 in __GI_raise (sig=11) at ../sysdeps/posix/raise.c:26
#3  0x000071cfbd62041c in KCrash::defaultCrashHandler(int) (sig=11) at /usr/src/debug/kcrash5/kcrash-5.114.0/src/kcrash.cpp:616
#4  0x000071cfbac5c710 in <signal handler called> () at /usr/lib/libc.so.6
#5  QObject::parent() const (this=<optimized out>, this=<optimized out>) at /usr/include/qt/QtCore/qobject.h:519
#6  Plasma::Containment::corona() const (this=this@entry=0x0) at /usr/src/debug/plasma-framework5/plasma-framework-5.114.0/src/plasma/containment.cpp:320
#7  0x0000572f18fb280f in WorkspaceScripting::Containment::Containment(Plasma::Containment*, WorkspaceScripting::ScriptEngine*)
    (this=0x572f1bfcdbd0, containment=0x0, engine=0x7ffc21a3d9f0, this=<optimized out>, containment=<optimized out>, engine=<optimized out>)
    at /usr/src/debug/plasma-workspace/plasma-workspace-5.27.10/shell/scripting/containment.cpp:45
#8  0x0000572f18fbca42 in WorkspaceScripting::ScriptEngine::createContainmentWrapper(QString const&, QString const&) (this=0x7ffc21a3d9f0, type=..., plugin=...)
    at /usr/src/debug/plasma-workspace/plasma-workspace-5.27.10/shell/scripting/scriptengine.cpp:417
#9  0x0000572f18fbccfa in WorkspaceScripting::ScriptEngine::V1::createContainment(QString const&, QString const&, QString const&)
    (this=0x572f1af937e0, type=..., defaultPlugin=..., plugin=<optimized out>)
    at /usr/src/debug/plasma-workspace/plasma-workspace-5.27.10/shell/scripting/scriptengine_v1.cpp:840
#10 0x0000572f18fbce94 in WorkspaceScripting::ScriptEngine::V1::newPanel(QString const&) (this=<optimized out>, plugin=<optimized out>)
    at /usr/src/debug/plasma-workspace/plasma-workspace-5.27.10/shell/scripting/scriptengine_v1.cpp:434
#11 0x0000572f18f752e5 in WorkspaceScripting::ScriptEngine::V1::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)
    (_o=0x572f1af937e0, _c=<optimized out>, _id=<optimized out>, _a=0x7ffc21a3cf90)
    at /usr/src/debug/plasma-workspace/build/shell/plasmashell_autogen/7KDSW62DQT/moc_scriptengine_v1.cpp:340
#12 0x0000572f18f76193 in WorkspaceScripting::ScriptEngine::V1::qt_metacall(QMetaObject::Call, int, void**)
    (this=0x572f1af937e0, _c=QMetaObject::InvokeMetaMethod, _id=49, _a=0x7ffc21a3cf90)
    at /usr/src/debug/plasma-workspace/build/shell/plasmashell_autogen/7KDSW62DQT/moc_scriptengine_v1.cpp:524
#13 0x000071cfbca7cff4 in QQmlObjectOrGadget::metacall(QMetaObject::Call, int, void**) const
    (this=0x7ffc21a3d230, type=QMetaObject::InvokeMetaMethod, index=<optimized out>, argv=<optimized out>)
    at /usr/src/debug/qt5-declarative/qtdeclarative/src/qml/qml/qqmlobjectorgadget.cpp:51
#14 0x000071cfbc97ebe1 in CallMethod
    (callType=<optimized out>, callArgs=0x7ffc21a3cf50, engine=<optimized out>, argTypes=<optimized out>, argCount=<optimized out>, returnType=<optimized out>, index=<optimized out>, object=<optimized out>) at /usr/include/qt/QtCore/qvarlengtharray.h:189
#15 CallPrecise(QQmlObjectOrGadget const&, QQmlPropertyData const&, QV4::ExecutionEngine*, QV4::CallData*, QMetaObject::Call)
    (object=..., data=..., engine=engine@entry=0x572f1c3a0ef0, callArgs=callArgs@entry=0x71cf851c0578, callType=callType@entry=QMetaObject::InvokeMetaMethod)
    at /usr/src/debug/qt5-declarative/qtdeclarative/src/qml/jsruntime/qv4qobjectwrapper.cpp:1553
#16 0x000071cfbc9801b7 in CallOverloaded
    (callType=QMetaObject::InvokeMetaMethod, propertyCache=<optimized out>, callArgs=0x71cf851c0578, engine=<optimized out>, data=..., object=...)
    at /usr/src/debug/qt5-declarative/qtdeclarative/src/qml/jsruntime/qv4qobjectwrapper.cpp:1629
#17 QV4::QObjectMethod::callInternal(QV4::Value const*, QV4::Value const*, int) const
    (this=<optimized out>, thisObject=<optimized out>, argv=<optimized out>, argc=<optimized out>)
    at /usr/src/debug/qt5-declarative/qtdeclarative/src/qml/jsruntime/qv4qobjectwrapper.cpp:2117
#18 0x000071cfbc9a63c1 in QV4::Runtime::CallProperty::call(QV4::ExecutionEngine*, QV4::Value const&, int, QV4::Value*, int)
    (engine=0x572f1c3a0ef0, baseRef=<optimized out>, nameIndex=<optimized out>, argv=0x71cf851c0520, argc=1)
    at /usr/src/debug/qt5-declarative/qtdeclarative/src/qml/jsruntime/qv4runtime.cpp:1448
#19 0x000071cfbc99025f in QV4::Moth::VME::interpret(QV4::CppStackFrame*, QV4::ExecutionEngine*, char const*)
    (frame=0x7ffc21a3d710, engine=0x572f1c3a0ef0, code=0x572f1987ec50 "\030\a0\004\032\a\006\026\006\002")
--Type <RET> for more, q to quit, c to continue without paging--c
    at /usr/src/debug/qt5-declarative/qtdeclarative/src/qml/jsruntime/qv4vme_moth.cpp:351
#20 0x000071cfbc993d24 in QV4::Moth::VME::exec(QV4::CppStackFrame*, QV4::ExecutionEngine*) (frame=<optimized out>, engine=<optimized out>)
    at /usr/src/debug/qt5-declarative/qtdeclarative/src/qml/jsruntime/qv4vme_moth.cpp:466
#21 0x000071cfbc93731a in QV4::Function::call(QV4::Value const*, QV4::Value const*, int, QV4::ExecutionContext const*)
    (this=<optimized out>, thisObject=<optimized out>, argv=<optimized out>, argc=<optimized out>, context=<optimized out>)
    at /usr/src/debug/qt5-declarative/qtdeclarative/src/qml/jsruntime/qv4function.cpp:69
#22 0x000071cfbc96eeed in QV4::Script::run(QV4::Value const*) (this=<optimized out>, thisObject=<optimized out>)
    at /usr/src/debug/qt5-declarative/qtdeclarative/src/qml/jsruntime/qv4script.cpp:162
#23 0x000071cfbc9040bb in QJSEngine::evaluate(QString const&, QString const&, int)
    (this=this@entry=0x7ffc21a3d9f0, program=<optimized out>, fileName=..., lineNumber=lineNumber@entry=1)
    at /usr/src/debug/qt5-declarative/qtdeclarative/src/qml/jsapi/qjsengine.cpp:545
#24 0x0000572f18fba2a4 in WorkspaceScripting::ScriptEngine::evaluateScript(QString const&, QString const&) (this=0x7ffc21a3d9f0, script=<optimized out>, path=...)
    at /usr/src/debug/plasma-workspace/plasma-workspace-5.27.10/shell/scripting/scriptengine.cpp:244


EXPECTED RESULT
no integer overflow, no crash

SOFTWARE/OS VERSIONS
Linux archer 6.7.0-arch3-1 #1 SMP PREEMPT_DYNAMIC Sat, 13 Jan 2024 14:37:14 +0000 x86_64 GNU/Linux

kdeplasma-addons 5.27.10-2
plasma-browser-integration 5.27.10-1
plasma-desktop 5.27.10-1
plasma-disks 5.27.10-1
plasma-firewall 5.27.10-1
plasma-framework5 5.114.0-1
plasma-integration 5.27.10-1
plasma-meta 5.27-4
plasma-nm 5.27.10-1
plasma-pa 5.27.10-1
plasma-sdk 5.27.10-1
plasma-systemmonitor 5.27.10-1
plasma-thunderbolt 5.27.10-1
plasma-vault 5.27.10-1
plasma-wayland-session 5.27.10-2
plasma-welcome 5.27.10-1
plasma-workspace 5.27.10-2
plasma-workspace-wallpapers 5.27.10-1
plasmatube 23.08.4-1

ADDITIONAL INFORMATION