diff --git a/mumble-1.2.19-limit-amount-of-messages.patch b/mumble-1.2.19-limit-amount-of-messages.patch new file mode 100644 index 0000000..1385954 --- /dev/null +++ b/mumble-1.2.19-limit-amount-of-messages.patch @@ -0,0 +1,195 @@ +From 44b9004d2c208b42c6f8ffa99938361e31f5a071 +From: MadMaurice +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 + + 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 users; + QQueue 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 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((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(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(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 + #endif + ++// was introduced in C++11 ++#if __cplusplus > 199711LL ++#include ++#else ++#include ++#endif ++ + #include "Connection.h" + #include "Net.h" + #include "Timer.h" +@@ -80,6 +87,26 @@ + + class Server; + ++#if __cplusplus > 199711L ++ typedef std::chrono::time_point 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 qmTargetCache; + QMap qmWhisperRedirect; + ++ LeakyBucket leakyBucket; ++ + int iLastPermissionCheck; + QMap qmPermissionSent; + #ifdef Q_OS_UNIX diff --git a/mumble-1.2.19-stricter-message-limit.patch b/mumble-1.2.19-stricter-message-limit.patch new file mode 100644 index 0000000..ae9bb2e --- /dev/null +++ b/mumble-1.2.19-stricter-message-limit.patch @@ -0,0 +1,22 @@ +From: 4761ca41ab1f611cd4a6d117f9f6cfd7c64f6b55 +From: MadMaurice +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(); + } + diff --git a/mumble.changes b/mumble.changes index 4650596..292d4fc 100644 --- a/mumble.changes +++ b/mumble.changes @@ -1,3 +1,14 @@ +------------------------------------------------------------------- +Fri Jul 12 23:30:49 UTC 2019 - Ferdinand Thiessen + +- 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 + ------------------------------------------------------------------- Wed Jun 26 13:05:06 UTC 2019 - Dirk Mueller diff --git a/mumble.spec b/mumble.spec index 875a6a5..1b5837f 100644 --- a/mumble.spec +++ b/mumble.spec @@ -16,27 +16,15 @@ # -%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 +%bcond_with mumble11x +%bcond_without bonjour # mumble must be able to talk to other clients which may use # differnt versions of celt. Since each celt release is # incompatible to each other mumble bundles some specific @@ -67,6 +55,11 @@ Patch3: initialize-soundfile-format.patch 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 @@ BuildRequires: pkgconfig(speexdsp) %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 @@ Source1: https://github.com/mumble-voip/mumble/releases/download/%{versio %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 @@ Conflicts: %{name}-32bit < %{version} 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 @@ won't be audible to other players. %patch4 -p1 %patch5 -p1 %patch6 -p1 +%patch7 -p1 +%patch8 -p1 %if !%{with system_celt} %if 0%{?snapshot:1} @@ -351,9 +339,6 @@ install -D -m 0755 %{SOURCE2} %{buildroot}%{_initddir}/mumble-server 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 @@ systemd-tmpfiles --create %{_libexecdir}/tmpfiles.d/mumble-server.conf || true %{_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