Hello community, here is the log from the commit of package mumble for openSUSE:Factory checked in at 2019-07-16 08:40:59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/mumble (Old) and /work/SRC/openSUSE:Factory/.mumble.new.1887 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "mumble" Tue Jul 16 08:40:59 2019 rev:56 rq:715233 version:1.2.19 Changes: -------- --- /work/SRC/openSUSE:Factory/mumble/mumble.changes 2019-07-04 15:44:20.550209527 +0200 +++ /work/SRC/openSUSE:Factory/.mumble.new.1887/mumble.changes 2019-07-16 08:41:09.347032857 +0200 @@ -1,0 +2,11 @@ +Fri Jul 12 23:30:49 UTC 2019 - Ferdinand Thiessen <[email protected]> + +- Added patches to fix boo#1123334 (CVE-2018-20743), instability + and crash due to crafted message flooding + * added mumble-1.2.19-limit-amount-of-messages.patch (backported + version of upstream patch) + * added mumble-1.2.19-stricter-message-limit.patch (backported + version of upstream patch) +- Cleaned spec file, removed old EOL openSUSE and Fedora versions + +------------------------------------------------------------------- New: ---- mumble-1.2.19-limit-amount-of-messages.patch mumble-1.2.19-stricter-message-limit.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ mumble.spec ++++++ --- /var/tmp/diff_new_pack.cyNodv/_old 2019-07-16 08:41:12.759033998 +0200 +++ /var/tmp/diff_new_pack.cyNodv/_new 2019-07-16 08:41:12.759033998 +0200 @@ -16,25 +16,13 @@ # -%if 0%{?suse_version} > 1100 -%bcond_without pulseaudio -%else -%if 0%{?fedora_version} > 9 -%bcond_without pulseaudio -%else -%bcond_with pulseaudio -%endif -%endif -%if 0%{?fedora_version} > 11 +%if 0%{?fedora_version} %bcond_without ice %else %bcond_with ice %endif -%if 0%{?suse_version} && 0%{?suse_version} < 1230 -%bcond_with systemd -%else +%bcond_without pulseaudio %bcond_without systemd -%endif %bcond_with mumble11x %bcond_without bonjour # mumble must be able to talk to other clients which may use @@ -67,6 +55,11 @@ Patch4: 0001-AudioOutput-do-not-use-non-existant-template-version.patch Patch5: add-speechd-include-path.patch Patch6: mumble-pr-3623-protobuf37.patch +# PATCH-FIX-UPSTREAM mumble-1.2.19-limit-amount-of-messages.patch -- https://github.com/mumble-voip/mumble/pull/3510 +Patch7: mumble-1.2.19-limit-amount-of-messages.patch +# PATCH-FIX-UPSTREAM mumble-1.2.19-stricter-message-limit.patch -- https://github.com/mumble-voip/mumble/pull/3512 +Patch8: mumble-1.2.19-stricter-message-limit.patch + %if 0%{?suse_version} > 1325 BuildRequires: libboost_headers-devel %else @@ -96,14 +89,10 @@ %endif %if 0%{?suse_version} BuildRequires: alsa-devel +BuildRequires: libopenssl-devel BuildRequires: libqt4-devel BuildRequires: pkg-config BuildRequires: update-desktop-files -%if 0%{?suse_version} > 1020 -BuildRequires: libopenssl-devel -%else -BuildRequires: openssl-devel -%endif %endif %if 0%{?fedora_version} BuildRequires: alsa-lib-devel @@ -135,10 +124,6 @@ %endif %if 0%{?suse_version} Requires: qt-sql-sqlite -%else -Requires: qt4-sqlite -%endif -%if 0%{?suse_version} > 1010 %ifarch x86_64 Recommends: %{name}-32bit Conflicts: %{name}-32bit < %{version} @@ -147,12 +132,13 @@ Recommends: %{name}-64bit Conflicts: %{name}-64bit < %{version} %endif +%else +Requires: qt4-sqlite %endif # %if 0%{?snapshot:1} Conflicts: mumble < %{version} Provides: mumble = %{version} -# %endif # @@ -191,6 +177,8 @@ %patch4 -p1 %patch5 -p1 %patch6 -p1 +%patch7 -p1 +%patch8 -p1 %if !%{with system_celt} %if 0%{?snapshot:1} @@ -351,9 +339,6 @@ ln -s %{_initddir}/mumble-server %{buildroot}%{_sbindir}/rcmumble-server %endif install -D -m 0644 %{SOURCE3} %{buildroot}%{_sysconfdir}/apparmor.d/usr.sbin.murmurd -%if 0%{?suse_version} < 1220 -sed -i -e 's,%{_bindir}/grep,/bin/grep,;s,%{_bindir}/sed,/bin/sed,' %{buildroot}%{_sysconfdir}/apparmor.d/usr.sbin.murmurd -%endif install -d -m 0755 %{buildroot}%{_bindir} # can be launched as user too but apparmor profile doesn't make # sense in that case. So use link to avoid the profile. @@ -466,9 +451,7 @@ %{_mandir}/man1/murmur-user-wrapper.* %dir %attr(-,mumble-server,mumble-server) %{_localstatedir}/lib/mumble-server %dir %{_localstatedir}/log/mumble-server -%if 0%{?suse_version} > 1310 %ghost %{_rundir}/mumble-server -%endif %dir %{_datadir}/appdata/ %{_datadir}/appdata/mumble.appdata.xml ++++++ mumble-1.2.19-limit-amount-of-messages.patch ++++++ >From 44b9004d2c208b42c6f8ffa99938361e31f5a071 From: MadMaurice <[email protected]> Date: Thu Aug 30 15:08:01 2018 +0200 Prevent instability and crash due to message flood This patch adds a rate limiting to selected patches. The underlying rate limiter used is the Leaky-Bucket algorithm. It allows for a burst of messages, but limits them after a specified amount of messages within a time frame. From: Ferdinand Thiessen <[email protected]> Modified this diff, to make it work with 1.2.19 tarball. "Backported" by manually change the 1.2.19 version according to the original diff. diff -Nur mumble-1.2.19/src/murmur/Messages.cpp new/src/murmur/Messages.cpp --- mumble-1.2.19/src/murmur/Messages.cpp 2017-01-27 07:48:33.000000000 +0100 +++ new/src/murmur/Messages.cpp 2019-07-13 00:45:48.281780195 +0200 @@ -42,6 +42,11 @@ #include "ServerUser.h" #include "Version.h" +#define RATELIMIT(user) \ + if (user->leakyBucket.ratelimit(1)) { \ + return; \ + } + #define MSG_SETUP(st) \ if (uSource->sState != st) { \ return; \ @@ -491,6 +496,10 @@ msg.set_session(pDstServerUser->uiSession); msg.set_actor(uSource->uiSession); + if (uSource == pDstServerUser) { + RATELIMIT(uSource); + } + if (msg.has_channel_id()) { Channel *c = qhChannels.value(msg.channel_id()); if (!c || (c == pDstServerUser->cChannel)) @@ -798,6 +807,8 @@ p = qhChannels.value(msg.parent()); if (! p) return; + } else { + RATELIMIT(uSource); } msg.clear_links(); @@ -1074,6 +1085,8 @@ QSet<ServerUser *> users; QQueue<Channel *> q; + RATELIMIT(uSource); + QString text = u8(msg.message()); bool changed = false; @@ -1176,6 +1189,8 @@ return; } + RATELIMIT(uSource); + if (msg.has_query() && msg.query()) { QStack<Channel *> chans; Channel *p; @@ -1417,6 +1432,8 @@ } void Server::msgVersion(ServerUser *uSource, MumbleProto::Version &msg) { + RATELIMIT(uSource); + if (msg.has_version()) uSource->uiVersion=msg.version(); if (msg.has_release()) diff -Nur mumble-1.2.19/src/murmur/ServerUser.cpp new/src/murmur/ServerUser.cpp --- mumble-1.2.19/src/murmur/ServerUser.cpp 2017-01-27 07:48:33.000000000 +0100 +++ new/src/murmur/ServerUser.cpp 2019-07-13 00:47:25.974498227 +0200 @@ -128,3 +128,61 @@ return static_cast<int>((sum * 1000000ULL) / elapsed); } +#if __cplusplus > 199711LL + +inline static +time_point now() { + return std::chrono::steady_clock::now(); +} + +inline static +unsigned long millisecondsBetween(time_point start, time_point end) { + return std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count(); +} + +#else + +inline static +time_point now() { + return clock(); +} + +inline static +unsigned long millisecondsBetween(time_point start, time_point end) { + return 1000 * (end - start) / CLOCKS_PER_SEC; +} + +#endif + +// Rate limiting: burst up to 30, 4 message per sec limit over longer time +LeakyBucket::LeakyBucket() : tokensPerSec(4), maxTokens(30), currentTokens(0) { + lastUpdate = now(); +} + +bool LeakyBucket::ratelimit(int tokens) { + // First remove tokens we leaked over time + time_point tnow = now(); + long ms = millisecondsBetween(lastUpdate, tnow); + + long drainTokens = (ms * tokensPerSec) / 1000; + + // Prevent constant starvation due to too many updates + if (drainTokens > 0) { + this->lastUpdate = tnow; + + this->currentTokens -= drainTokens; + if (this->currentTokens < 0) { + this->currentTokens = 0; + } + } + + // Then try to add tokens + bool limit = this->currentTokens > ((static_cast<long>(maxTokens)) - tokens); + + // If the bucket is not overflowed, allow message and add tokens + if (!limit) { + this->currentTokens += tokens; + } + + return limit; +} diff -Nur mumble-1.2.19/src/murmur/ServerUser.h new/src/murmur/ServerUser.h --- mumble-1.2.19/src/murmur/ServerUser.h 2017-01-27 07:48:33.000000000 +0100 +++ new/src/murmur/ServerUser.h 2019-07-13 00:49:28.023395272 +0200 @@ -40,6 +40,13 @@ #include <winsock2.h> #endif +// <chrono> was introduced in C++11 +#if __cplusplus > 199711LL +#include <chrono> +#else +#include <ctime> +#endif + #include "Connection.h" #include "Net.h" #include "Timer.h" @@ -80,6 +87,26 @@ class Server; +#if __cplusplus > 199711L + typedef std::chrono::time_point<std::chrono::steady_clock> time_point; +#else + typedef clock_t time_point; +#endif + +// Simple algorithm for rate limiting +class LeakyBucket { + private: + unsigned int tokensPerSec, maxTokens; + long currentTokens; + time_point lastUpdate; + + public: + // Returns true if packets should be dropped + bool ratelimit(int tokens); + + LeakyBucket(); +}; + class ServerUser : public Connection, public User { private: Q_OBJECT @@ -119,6 +146,8 @@ QMap<int, TargetCache> qmTargetCache; QMap<QString, QString> qmWhisperRedirect; + LeakyBucket leakyBucket; + int iLastPermissionCheck; QMap<int, unsigned int> qmPermissionSent; #ifdef Q_OS_UNIX ++++++ mumble-1.2.19-stricter-message-limit.patch ++++++ From: 4761ca41ab1f611cd4a6d117f9f6cfd7c64f6b55 From: MadMaurice <[email protected]> Date: Fri Aug 31 00:01:40 2018 +0200 Lower bucket params Use 1 tokens per second and 5 burst instead of 4 tokens per second and 30 burst diff -Nur old/src/murmur/ServerUser.cpp new/src/murmur/ServerUser.cpp --- old/src/murmur/ServerUser.cpp 2019-07-13 01:28:14.972194419 +0200 +++ new/src/murmur/ServerUser.cpp 2019-07-13 01:29:36.724758470 +0200 @@ -154,8 +154,8 @@ #endif -// Rate limiting: burst up to 30, 4 message per sec limit over longer time -LeakyBucket::LeakyBucket() : tokensPerSec(4), maxTokens(30), currentTokens(0) { +// Rate limiting: burst up to 5, 1 message per sec limit over longer time +LeakyBucket::LeakyBucket() : tokensPerSec(1), maxTokens(5), currentTokens(0) { lastUpdate = now(); }
