[Libreoffice-commits] online.git: kit/Kit.cpp net/ServerSocket.hpp net/Socket.cpp net/Socket.hpp wsd/LOOLWSD.cpp

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Sat Mar 30 21:37:25 UTC 2019


 kit/Kit.cpp          |    8 ---
 net/ServerSocket.hpp |   55 +----------------------
 net/Socket.cpp       |  121 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 net/Socket.hpp       |    3 +
 wsd/LOOLWSD.cpp      |   13 +----
 5 files changed, 131 insertions(+), 69 deletions(-)

New commits:
commit 201bcb0762c838e75b61f030725c9bf0ba59c1c3
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Sat Mar 30 21:07:58 2019 +0000
Commit:     Michael Meeks <michael.meeks at collabora.com>
CommitDate: Sat Mar 30 21:37:05 2019 +0000

    Use peercreds to identify processes connecting rather than URL params.
    
    Change-Id: I241e80962fb8cf2f3fff1bb4be81d9f0ee74c648

diff --git a/kit/Kit.cpp b/kit/Kit.cpp
index 819fb2698..ff4a3a7ed 100644
--- a/kit/Kit.cpp
+++ b/kit/Kit.cpp
@@ -2485,11 +2485,8 @@ void lokit_main(
 
         LOG_INF("Process is ready.");
 
-        static const std::string pid = std::to_string(Process::id());
         std::string pathAndQuery(NEW_CHILD_URI);
-        pathAndQuery.append("?pid=");
-        pathAndQuery.append(pid);
-        pathAndQuery.append("&jailid=");
+        pathAndQuery.append("?jailid=");
         pathAndQuery.append(jailId);
         if (queryVersion)
         {
@@ -2522,7 +2519,6 @@ void lokit_main(
 
         // Dummies
         const std::string jailId = "jailid";
-        const std::string pid = "101";
 
 #endif // MOBILEAPP
 
@@ -2530,7 +2526,7 @@ void lokit_main(
         mainKit.runOnClientThread(); // We will do the polling on this thread.
 
         std::shared_ptr<SocketHandlerInterface> websocketHandler =
-            std::make_shared<KitWebSocketHandler>("child_ws_" + pid, loKit, jailId, mainKit);
+            std::make_shared<KitWebSocketHandler>("child_ws", loKit, jailId, mainKit);
 #if !MOBILEAPP
         mainKit.insertNewUnixSocket(MasterLocation, pathAndQuery, websocketHandler);
 #else
diff --git a/net/ServerSocket.hpp b/net/ServerSocket.hpp
index 79a7795bc..dd07af4fe 100644
--- a/net/ServerSocket.hpp
+++ b/net/ServerSocket.hpp
@@ -61,58 +61,7 @@ public:
     /// Accepts an incoming connection (Servers only).
     /// Does not retry on error.
     /// Returns a valid Socket shared_ptr on success only.
-    std::shared_ptr<Socket> accept()
-    {
-        // Accept a connection (if any) and set it to non-blocking.
-        // There still need the client's address to filter request from POST(call from REST) here.
-#if !MOBILEAPP
-        struct sockaddr_in6 clientInfo;
-        socklen_t addrlen = sizeof(clientInfo);
-        const int rc = ::accept4(getFD(), (struct sockaddr *)&clientInfo, &addrlen, SOCK_NONBLOCK);
-#else
-        const int rc = fakeSocketAccept4(getFD());
-#endif
-        LOG_DBG("Accepted socket #" << rc << ", creating socket object.");
-        try
-        {
-            // Create a socket object using the factory.
-            if (rc != -1)
-            {
-#if !MOBILEAPP
-                char addrstr[INET6_ADDRSTRLEN];
-
-                const void *inAddr;
-                if (clientInfo.sin6_family == AF_INET)
-                {
-                    auto ipv4 = (struct sockaddr_in *)&clientInfo;
-                    inAddr = &(ipv4->sin_addr);
-                }
-                else
-                {
-                    auto ipv6 = (struct sockaddr_in6 *)&clientInfo;
-                    inAddr = &(ipv6->sin6_addr);
-                }
-
-                inet_ntop(clientInfo.sin6_family, inAddr, addrstr, sizeof(addrstr));
-                std::shared_ptr<Socket> _socket = _sockFactory->create(rc);
-                _socket->setClientAddress(addrstr);
-                LOG_DBG("Accepted socket has family " << clientInfo.sin6_family <<
-                        " address " << _socket->clientAddress());
-#else
-                std::shared_ptr<Socket> _socket = _sockFactory->create(rc);
-                _socket->setClientAddress("dummy");
-#endif
-                return _socket;
-            }
-            return std::shared_ptr<Socket>(nullptr);
-        }
-        catch (const std::exception& ex)
-        {
-            LOG_SYS("Failed to create client socket #" << rc << ". Error: " << ex.what());
-        }
-
-        return nullptr;
-    }
+    virtual std::shared_ptr<Socket> accept();
 
     int getPollEvents(std::chrono::steady_clock::time_point /* now */,
                       int & /* timeoutMaxMs */) override
@@ -143,6 +92,7 @@ public:
 private:
     Socket::Type _type;
     SocketPoll& _clientPoller;
+protected:
     std::shared_ptr<SocketFactory> _sockFactory;
 };
 
@@ -155,6 +105,7 @@ public:
     {
     }
     virtual bool bind(Type, int) { assert(false); return false; }
+    virtual std::shared_ptr<Socket> accept() override;
     std::string bind();
 
 private:
diff --git a/net/Socket.cpp b/net/Socket.cpp
index a1762352e..02fb7f972 100644
--- a/net/Socket.cpp
+++ b/net/Socket.cpp
@@ -16,6 +16,7 @@
 #include <iomanip>
 #include <stdio.h>
 #include <unistd.h>
+#include <sys/types.h>
 #include <zlib.h>
 
 #include <Poco/DateTime.h>
@@ -398,7 +399,8 @@ void StreamSocket::dumpState(std::ostream& os)
     int events = getPollEvents(std::chrono::steady_clock::now(), timeoutMaxMs);
     os << "\t" << getFD() << "\t" << events << "\t"
        << _inBuffer.size() << "\t" << _outBuffer.size() << "\t"
-       << " r: " << _bytesRecvd << "\t w: " << _bytesSent << "\t";
+       << " r: " << _bytesRecvd << "\t w: " << _bytesSent << "\t"
+       << clientAddress() << "\t";
     _socketHandler->dumpState(os);
     if (_inBuffer.size() > 0)
         Util::dumpHex(os, "\t\tinBuffer:\n", "\t\t", _inBuffer);
@@ -483,6 +485,123 @@ bool ServerSocket::bind(Type type, int port)
 #endif
 }
 
+std::shared_ptr<Socket> ServerSocket::accept()
+{
+    // Accept a connection (if any) and set it to non-blocking.
+    // There still need the client's address to filter request from POST(call from REST) here.
+#if !MOBILEAPP
+    assert(_type != Socket::Type::Unix);
+
+    struct sockaddr_in6 clientInfo;
+    socklen_t addrlen = sizeof(clientInfo);
+    const int rc = ::accept4(getFD(), (struct sockaddr *)&clientInfo, &addrlen, SOCK_NONBLOCK);
+#else
+    const int rc = fakeSocketAccept4(getFD());
+#endif
+    LOG_DBG("Accepted socket #" << rc << ", creating socket object.");
+    try
+    {
+        // Create a socket object using the factory.
+        if (rc != -1)
+        {
+            std::shared_ptr<Socket> _socket = _sockFactory->create(rc);
+
+#if !MOBILEAPP
+            char addrstr[INET6_ADDRSTRLEN];
+
+            const void *inAddr;
+            if (clientInfo.sin6_family == AF_INET)
+            {
+                auto ipv4 = (struct sockaddr_in *)&clientInfo;
+                inAddr = &(ipv4->sin_addr);
+            }
+            else
+            {
+                auto ipv6 = (struct sockaddr_in6 *)&clientInfo;
+                inAddr = &(ipv6->sin6_addr);
+            }
+
+            inet_ntop(clientInfo.sin6_family, inAddr, addrstr, sizeof(addrstr));
+            _socket->setClientAddress(addrstr);
+
+            LOG_DBG("Accepted socket has family " << clientInfo.sin6_family <<
+                    " address " << _socket->clientAddress());
+#endif
+            return _socket;
+        }
+        return std::shared_ptr<Socket>(nullptr);
+    }
+    catch (const std::exception& ex)
+    {
+        LOG_SYS("Failed to create client socket #" << rc << ". Error: " << ex.what());
+    }
+
+    return nullptr;
+}
+
+int Socket::getPid() const
+{
+    struct ucred creds;
+    socklen_t credSize = sizeof(struct ucred);
+    if (getsockopt(_fd, SOL_SOCKET, SO_PEERCRED, &creds, &credSize) < 0)
+    {
+        LOG_TRC("Failed to get pid via peer creds on " << _fd << " " << strerror(errno));
+        return -1;
+    }
+    return creds.pid;
+}
+
+std::shared_ptr<Socket> LocalServerSocket::accept()
+{
+#if !MOBILEAPP
+    const int rc = ::accept4(getFD(), nullptr, nullptr, SOCK_NONBLOCK);
+#else
+    const int rc = fakeSocketAccept4(getFD());
+#endif
+    try
+    {
+        LOG_DBG("Accepted prisoner socket #" << rc << ", creating socket object.");
+        if (rc < 0)
+            return std::shared_ptr<Socket>(nullptr);
+
+        std::shared_ptr<Socket> _socket = _sockFactory->create(rc);
+#if MOBILEAPP
+        // Sanity check this incoming socket
+        struct ucred creds;
+        socklen_t credSize = sizeof(struct ucred);
+        if (getsockopt(GetFD(), SOL_SOCKET, SO_PEERCRED, &creds, &credSize) < 0)
+        {
+            LOG_ERR("Failed to get peer creds on " << GetFD() << " " << strerror(errno));
+            ::close(rc);
+            return std::shared_ptr<Socket>(nullptr);
+        }
+
+        int uid = getuid();
+        int gid = getgid();
+        if (creds.uid != uid || cred.gid != gid)
+        {
+            LOG_ERR("Peercred mis-match on domain socket - closing connection. uid: " <<
+                    creds.uid << "vs." << uid << " gid: " << creds.gid << "vs." << gid);
+            ::close(rc);
+            return std::shared_ptr<Socket>(nullptr);
+        }
+        std::string addr("uds-to-pid-");
+        addr.append(std::to_string(creds.pid));
+        _socket->setClientAddress(addr);
+
+        std::shared_ptr<Socket> _socket = _sockFactory->create(rc);
+        LOG_DBG("Accepted socket is UDS - address " << addr <<
+                " and pid/gid " << creds.pid << "/" << creds.gid);
+#endif
+        return _socket;
+    }
+    catch (const std::exception& ex)
+    {
+        LOG_SYS("Failed to create client socket #" << rc << ". Error: " << ex.what());
+        return std::shared_ptr<Socket>(nullptr);
+    }
+}
+
 /// Returns true on success only.
 std::string LocalServerSocket::bind()
 {
diff --git a/net/Socket.hpp b/net/Socket.hpp
index 10460fe4b..c2355b7b7 100644
--- a/net/Socket.hpp
+++ b/net/Socket.hpp
@@ -173,6 +173,9 @@ public:
     }
 
 #if !MOBILEAPP
+    /// Uses peercreds to get prisoner PID if present or -1
+    int getPid() const;
+
     /// Sets the kernel socket send buffer in size bytes.
     /// Note: TCP will allocate twice this size for admin purposes,
     /// so a subsequent call to getSendBufferSize will return
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index 0b3ccfe86..b4060d643 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -1825,22 +1825,15 @@ private:
 
             // New Child is spawned.
             const Poco::URI::QueryParameters params = requestURI.getQueryParameters();
-            Poco::Process::PID pid = -1;
+            int pid = socket->getPid();
             std::string jailId;
             for (const auto& param : params)
             {
-                if (param.first == "pid")
-                {
-                    pid = std::stoi(param.second);
-                }
-                else if (param.first == "jailid")
-                {
+                if (param.first == "jailid")
                     jailId = param.second;
-                }
+
                 else if (param.first == "version")
-                {
                     LOOLWSD::LOKitVersion = param.second;
-                }
             }
 
             if (pid <= 0)


More information about the Libreoffice-commits mailing list