[Libreoffice-commits] online.git: 2 commits - common/Session.cpp common/Unit.hpp test/UnitFuzz.cpp wsd/LOOLWSD.cpp

Michael Meeks michael.meeks at collabora.com
Thu Dec 8 14:53:19 UTC 2016


 common/Session.cpp |   17 ++++++--
 common/Unit.hpp    |   15 +++++++
 test/UnitFuzz.cpp  |  102 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 wsd/LOOLWSD.cpp    |    6 ++-
 4 files changed, 130 insertions(+), 10 deletions(-)

New commits:
commit 4c2e59c1f22bdf74167e7fad97e7aa9549d03d3e
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Thu Dec 8 14:52:31 2016 +0000

    Don't take down WSD with an assert on a badly formed URI.

diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index 277ace6..16802e1 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -1256,7 +1256,11 @@ public:
     {
         LOG_TRC("Child connection with URI [" << request.getURI() << "].");
         assert(request.serverAddress().port() == MasterPortNumber);
-        assert(request.getURI().find(NEW_CHILD_URI) == 0);
+        if (request.getURI().find(NEW_CHILD_URI) != 0)
+        {
+            LOG_ERR("Invalid incoming URI.");
+            return;
+        }
 
         // New Child is spawned.
         const auto params = Poco::URI(request.getURI()).getQueryParameters();
commit 7cf77c26f7c923a2ea4f34410f0b83f84c37dde6
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Wed Dec 7 21:32:08 2016 +0000

    Improved fuzzer - to fuzz input.
    
    Pass --unitlib=test/.libs/unit-fuzz.so to loolwsd to enable.

diff --git a/common/Session.cpp b/common/Session.cpp
index e1a3f36..5ead325 100644
--- a/common/Session.cpp
+++ b/common/Session.cpp
@@ -39,6 +39,7 @@
 #include "Log.hpp"
 #include "TileCache.hpp"
 #include "Util.hpp"
+#include "Unit.hpp"
 
 using namespace LOOLProtocol;
 
@@ -222,22 +223,30 @@ bool LOOLSession::handleInput(const char *buffer, int length)
 {
     assert(buffer != nullptr);
 
-    const auto summary = getAbbreviatedMessage(buffer, length);
     try
     {
-        LOG_TRC(getName() << ": Recv: " << summary);
+        std::unique_ptr< std::vector<char> > replace;
+        if (UnitBase::get().filterSessionInput(this, buffer, length, replace))
+        {
+            buffer = replace->data();
+            length = replace->size();
+        }
+
+        LOG_TRC(getName() << ": Recv: " << getAbbreviatedMessage(buffer, length));
 
         return _handleInput(buffer, length);
     }
     catch (const Exception& exc)
     {
-        LOG_ERR("LOOLSession::handleInput: Exception while handling [" << summary <<
+        LOG_ERR("LOOLSession::handleInput: Exception while handling [" <<
+                getAbbreviatedMessage(buffer, length) <<
                 "] in " << getName() << ": " << exc.displayText() <<
                 (exc.nested() ? " (" + exc.nested()->displayText() + ")" : ""));
     }
     catch (const std::exception& exc)
     {
-        LOG_ERR("LOOLSession::handleInput: Exception while handling [" << summary << "]: " << exc.what());
+        LOG_ERR("LOOLSession::handleInput: Exception while handling [" <<
+                getAbbreviatedMessage(buffer, length) << "]: " << exc.what());
     }
 
     return false;
diff --git a/common/Unit.hpp b/common/Unit.hpp
index 7b6c6f8..40f20b3 100644
--- a/common/Unit.hpp
+++ b/common/Unit.hpp
@@ -38,6 +38,7 @@ namespace Poco
     }
 }
 
+class LOOLSession;
 class StorageBase;
 
 typedef UnitBase *(CreateUnitHooksFunction)();
@@ -88,6 +89,20 @@ public:
     /// Tweak the return value from the process.
     virtual void returnValue(int& /* retValue */);
 
+    /// Input message either for WSD or Kit
+    virtual bool filterSessionInput(LOOLSession *, const char */* buffer */,
+                                    int /* length */,
+                                    std::unique_ptr< std::vector<char> > & /* replace */)
+    {
+        return false;
+    }
+
+    static UnitBase& get()
+    {
+        assert(Global);
+        return *static_cast<UnitBase *>(Global);
+    }
+
 private:
     void setHandle(void *dlHandle) { _dlHandle = dlHandle; }
     static UnitBase *linkAndCreateUnit(UnitType type, const std::string& unitLibPath);
diff --git a/test/UnitFuzz.cpp b/test/UnitFuzz.cpp
index fba1d73..1363ae7 100644
--- a/test/UnitFuzz.cpp
+++ b/test/UnitFuzz.cpp
@@ -13,6 +13,7 @@
 #include <iostream>
 #include <sys/types.h>
 #include <dirent.h>
+#include <random>
 
 #include "Common.hpp"
 #include "IoUtil.hpp"
@@ -23,22 +24,113 @@
 
 #include <Poco/Timestamp.h>
 #include <Poco/StringTokenizer.h>
+#include <Poco/Net/HTTPServerRequest.h>
 
 // Inside the WSD process
 class UnitFuzz : public UnitWSD
 {
+    std::random_device _rd;
+    std::mt19937 _mt;
+    std::uniform_int_distribution<> _dist;
 public:
-    UnitFuzz()
+    UnitFuzz() :
+        _mt(_rd()),
+        _dist(0, 1000)
     {
-        std::cerr << "UnitFuzz startup\n";
+        std::cerr << "\n\nYour WSD process is being randomly fuzzed\n\n\n";
         setHasKitHooks();
+        setTimeout(3600 * 1000); /* one hour */
+    }
+
+    std::string corruptString(const std::string &str)
+    {
+        std::string ret;
+        for ( auto it = str.begin(); it != str.end(); ++it)
+        {
+            int op = _dist(_mt);
+            if (op < 10) {
+                switch (op) {
+                    case 0:
+                        ret += 0xff;
+                        break;
+                case 1:
+                case 3:
+                    ret += *it & 0x80;
+                    break;
+                default:
+                    ret += *it ^ _dist(_mt);
+                    break;
+                }
+            }
+        }
+        return ret;
+    }
+
+    /*
+     * Note: Fuzzers are fragile and their performance is rather
+     * sensitive. Please avoid random code tweaking in this method.
+     */
+    virtual bool filterSessionInput(LOOLSession *, const char *buffer,
+                                    int length,
+                                    std::unique_ptr< std::vector<char> > &replace) override
+    {
+        // Avoid fuzzing most messages
+        if (_dist(_mt) < 875)
+            return false;
+
+        auto fuzzed = new std::vector<char>();
+        fuzzed->assign(buffer, buffer+length);
+
+        int resize = _dist(_mt);
+        if (resize < 50) { // truncate
+            size_t shrink = (fuzzed->size() * _dist(_mt))/1000;
+            fuzzed->resize(shrink);
+
+        } else if (resize < 200) {
+            bool prepend = resize < 100;
+            bool middle = resize < 150;
+            size_t count = 1 + _dist(_mt)/100;
+            for (size_t i = 0; i < count; ++i)
+            {
+                char c = (_dist(_mt) * 256 / 1000);
+                if (prepend)
+                    fuzzed->insert(fuzzed->begin(), c);
+                else if (middle)
+                    fuzzed->insert(fuzzed->begin() + fuzzed->size()/2, c);
+                else
+                    fuzzed->push_back(c);
+            }
+        }
+
+        int numCorrupt = (_dist(_mt) / 100) - 75;
+        for (int i = 0; i < numCorrupt; ++i)
+        {
+            size_t offset = (_dist(_mt) * fuzzed->size() - 1) / 1000;
+            char c = (*fuzzed)[offset];
+            int change = _dist(_mt);
+            if (change < 256)
+                c ^= change;
+            else if (c >= '0' && c <= '9')
+                c = '0' + (change - 256)/100;
+            else
+                c |= 0x80;
+        }
+
+        replace.reset(fuzzed);
+
+        return true;
     }
 
     virtual bool filterHandleRequest(
         TestRequest /* type */,
-        Poco::Net::HTTPServerRequest& /* request */,
+        Poco::Net::HTTPServerRequest& request,
         Poco::Net::HTTPServerResponse& /* response */) override
     {
+        if (_dist(_mt) < 10) // 1%
+        {
+            std::cerr << "Mangle request URI\n";
+            request.setURI(corruptString(request.getURI()));
+        }
         return false;
     }
 };
@@ -49,12 +141,12 @@ class UnitKitFuzz : public UnitKit
 public:
     UnitKitFuzz()
     {
-        std::cerr << "UnitKit Fuzz init !\n";
+        std::cerr << "\n\nYour KIT process has fuzzing hooks\n\n\n";
+        setTimeout(3600 * 1000); /* one hour */
     }
     ~UnitKitFuzz()
     {
     }
-
     virtual bool filterKitMessage(const std::shared_ptr<LOOLWebSocket> & /* ws */,
                                   std::string & /* message */) override
     {


More information about the Libreoffice-commits mailing list