Fix handling of unknown netlink messages 75/129475/12
authorPiotr Sawicki <p.sawicki2@partner.samsung.com>
Tue, 16 May 2017 11:44:08 +0000 (13:44 +0200)
committerZofia Abramowska <z.abramowska@samsung.com>
Wed, 31 May 2017 11:21:51 +0000 (13:21 +0200)
A severe netlink error should stop the service, but other kinds of errors,
like inability to parse a netlink message by libnetfilter_queue, should only
be registered in the system log. These errors may happen when Nether issues
a verdict to a nonexistent packet (in result the kernel replies with an
error message).

Change-Id: I69bb811d34a993c28a2cde0cb0e8290c25c895d3

include/nether_Manager.h
include/nether_Utils.h
src/nether_Manager.cpp
src/nether_Netlink.cpp
src/nether_Utils.cpp

index 9ba67ab..22ff774 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2015 - 2017 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *  Contact: Roman Kubiak (r.kubiak@samsung.com)
  *
@@ -58,6 +58,7 @@ class NetherManager : public NetherVerdictListener, public NetherProcessedPacket
                int auditDescriptor;
 #endif // HAVE_AUDIT
                sigset_t signalMask;
+               char m_packetBuffer[NETHER_PACKET_BUFFER_SIZE] __attribute__((aligned));
 };
 
 #endif
index 4a888d6..371d5cd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2015 - 2017 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *  Contact: Roman Kubiak (r.kubiak@samsung.com)
  *
@@ -45,4 +45,5 @@ std::string protocolToString(const NetherProtocolType protocolType);
 std::string packetToString(const NetherPacket &packet);
 template<typename ... Args> std::string stringFormat(const char* format, Args ... args);
 std::vector<std::string> tokenize(const std::string &str, const std::string &delimiters);
+std::string bufferToHexDumpString(const char *data, int size);
 #endif // NETHER_UTILS_H
index 1b0725c..445ec52 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2015 -2017 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *  Contact: Roman Kubiak (r.kubiak@samsung.com)
  *
@@ -26,6 +26,7 @@
 #include "nether_CynaraBackend.h"
 #include "nether_FileBackend.h"
 #include "nether_DummyBackend.h"
+#include "nether_Utils.h"
 
 NetherManager::NetherManager(const NetherConfig &_netherConfig)
        :       netherPrimaryPolicyBackend(nullptr),
@@ -148,7 +149,7 @@ bool NetherManager::process()
 
                if(FD_ISSET(netlinkDescriptor, &watchedReadDescriptorsSet))
                        if(!handleNetlinkpacket())
-                               break;
+                               return false;
 
                if (backendDescriptor == -1)
                        continue;
@@ -190,23 +191,21 @@ bool NetherManager::handleNetlinkpacket()
 {
        LOGD("netlink descriptor active");
        int packetReadSize;
-       NetherPacket receivedPacket;
-       char packetBuffer[NETHER_PACKET_BUFFER_SIZE] __attribute__((aligned));
 
        /* some data arrives on netlink, read it */
-       if((packetReadSize = recv(netlinkDescriptor, packetBuffer, sizeof(packetBuffer), 0)) >= 0)
+       if((packetReadSize = recv(netlinkDescriptor, m_packetBuffer, sizeof(m_packetBuffer), 0)) >= 0)
        {
                /* try to process the packet using netfilter_queue library, fetch packet info
                    needed for making a decision about it */
-               if(netherNetlink->processPacket(packetBuffer, packetReadSize))
+               if(netherNetlink->processPacket(m_packetBuffer, packetReadSize))
                {
                        return (true);
                }
                else
                {
-                       /* if we can't process the incoming packets, it's bad. Let's exit now */
-                       LOGE("Failed to process netlink received packet, refusing to continue");
-                       return (false);
+                       LOGE("Failed to process netlink packet");
+                       LOGE(bufferToHexDumpString(m_packetBuffer, packetReadSize));
+                       return (true);
                }
        }
 
index a0ef40a..0f1ee49 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2015 - 2017 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *  Contact: Roman Kubiak (r.kubiak@samsung.com)
  *
@@ -160,7 +160,8 @@ int NetherNetlink::callback(struct nfq_q_handle *, struct nfgenmsg *, struct nfq
        if(nfq_get_uid(nfa, &packet.uid) == 0)
                LOGW("Failed to get uid for packet id=" << packet.id);
 
-       nfq_get_gid(nfa, &packet.gid);
+       if (nfq_get_gid(nfa, &packet.gid) == 0)
+               LOGW("Failed to get gid for packet id=" << packet.id);
 
        secctxSize = nfq_get_secctx(nfa, &secctx);
 
index 7726dd6..e68d3df 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2015 - 2017 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *  Contact: Roman Kubiak (r.kubiak@samsung.com)
  *
@@ -24,6 +24,9 @@
 
 #include "nether_Utils.h"
 
+#include <iomanip>
+#include <sstream>
+
 NetherVerdict stringToVerdict(char *verdictAsString)
 {
        if(verdictAsString)
@@ -189,3 +192,44 @@ std::vector<std::string> tokenize(const std::string &str, const std::string &del
         v.emplace_back(str, start, str.length() - start); // add what's left of the string
     return v;
 }
+
+std::string bufferToHexDumpString(const char *data, int size)
+{
+       const int numCols = 16;
+       const uint8_t *buffer = reinterpret_cast<const uint8_t *>(data);
+       std::stringstream ss;
+
+       ss << "Buffer size: " << size << " B\n" << ss.str();
+
+       ss << std::hex << std::setfill('0');
+
+       for (int offset = 0; offset < size; offset += numCols)
+       {
+               ss << std::setw(sizeof(size) * 2)
+                  << offset << ": ";
+
+               for (int c = 0; c < numCols; c++)
+               {
+                       if ((offset + c) < size)
+                       {
+                               ss << std::setw(2)
+                                  << (unsigned int)buffer[offset + c] << " ";
+                       }
+                       else
+                       {
+                               ss << "   ";
+                       }
+               }
+
+               ss << "  ";
+
+               for (int c = 0; c < numCols && (offset + c) < size; c++)
+               {
+                       ss << (isprint(data[offset + c]) ? data[offset + c] : '.');
+               }
+
+               ss << std::endl;
+       }
+
+       return ss.str();
+}