Add the management of audit rules in netlink audit 41/136641/4
authorSungbae Yoo <sungbae.yoo@samsung.com>
Fri, 30 Jun 2017 11:59:12 +0000 (20:59 +0900)
committerSungbae Yoo <sungbae.yoo@samsung.com>
Tue, 11 Jul 2017 02:52:29 +0000 (11:52 +0900)
Signed-off-by: Sungbae Yoo <sungbae.yoo@samsung.com>
Change-Id: I22f2c5c44015d8dc57b97e69d87413ea2e06c1fa

include/klay/netlink/audit-rule.h [new file with mode: 0644]
include/klay/netlink/audit.h
include/klay/netlink/netlink.h
src/CMakeLists.txt
src/netlink/audit-rule.cpp [new file with mode: 0644]
src/netlink/audit.cpp
src/netlink/netlink.cpp

diff --git a/include/klay/netlink/audit-rule.h b/include/klay/netlink/audit-rule.h
new file mode 100644 (file)
index 0000000..16faaad
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *  Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+#ifndef __RUNTIME_NETLINK_AUDIT_RULE_H__
+#define __RUNTIME_NETLINK_AUDIT_RULE_H__
+
+#include <vector>
+
+#include <linux/audit.h>
+
+namespace netlink {
+
+class AuditRule final {
+public:
+       AuditRule();
+       AuditRule(std::vector<char>& buf);
+       ~AuditRule();
+
+       void setSystemCall(unsigned int syscall);
+       void unsetSystemCall(unsigned int syscall);
+       void setAllSystemCalls();
+       void clearAllSystemCalls();
+       std::vector<unsigned int> getSystemCalls() const;
+
+       void setReturn(unsigned int val);
+       void unsetReturn();
+       unsigned int getReturn() const;
+       bool hasReturn() const;
+
+       void setKey(const std::string &name);
+       void unsetKey();
+       const std::string getkey() const;
+       bool hasKey() const;
+
+       const char *data() const
+       {
+               return buf.data();
+       }
+
+       unsigned int size() const
+       {
+               return buf.size();
+       }
+
+private:
+       std::vector<char> buf;
+};
+
+} // namespace runtime
+
+#endif //!__RUNTIME_NETLINK_AUDIT_RULE_H__
index 61a2ef640946ccb3c91373917173da3ff4851a8f..5098d23ce2f3b871c247ffd6a760caf78cd59abb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
 
 #include <klay/mainloop.h>
 #include <klay/netlink/netlink.h>
+#include <klay/netlink/audit-rule.h>
 
 namespace netlink {
 
@@ -33,16 +34,20 @@ public:
        typedef std::function<void(Message&)> MessageHandler;
 
        Audit();
-    Audit(Audit&&);
-    Audit(const Audit&) = delete;
-    ~Audit();
+       Audit(Audit&&);
+       Audit(const Audit&) = delete;
+       ~Audit();
 
-    Audit& operator=(const Audit&) = delete;
+       Audit& operator=(const Audit&) = delete;
 
        void setPID(pid_t pid);
        void setEnabled(int enabled);
        int isEnabled();
 
+       std::vector<AuditRule> getRules();
+       void addRule(const AuditRule& rule);
+       void removeRule(const AuditRule& rule);
+
        void setMainloop(runtime::Mainloop *ml);
        void setMessageHandler(MessageHandler&& handler);
 
index 10e5a8003eb3468cec7918fa704c8e84440e4aae..0e12e11e37cbbe6a8ac9a593e7ede86101d2ba24 100644 (file)
@@ -28,11 +28,11 @@ namespace netlink {
 class Netlink final {
 public:
        Netlink(int);
-    Netlink(Netlink&&);
-    Netlink(const Netlink&) = delete;
-    ~Netlink();
+       Netlink(Netlink&&);
+       Netlink(const Netlink&) = delete;
+       ~Netlink();
 
-    Netlink& operator=(const Netlink&) = delete;
+       Netlink& operator=(const Netlink&) = delete;
 
        void send(const void *data, unsigned int size);
        void recv(void *data, unsigned int size, int options = 0);
index c135d233b980821f16070db5bfb4abb54d05f98b..7a15c38cb14f453c9921edaa6f3b5ac1ac618938 100755 (executable)
@@ -50,6 +50,7 @@ SET (KLAY_SOURCES             ${KLAY_SRC}/error.cpp
                                                ${KLAY_SRC}/audit/audit-trail.cpp
                                                ${KLAY_SRC}/netlink/audit.cpp
                                                ${KLAY_SRC}/netlink/netlink.cpp
+                                               ${KLAY_SRC}/netlink/audit-rule.cpp
 )
 
 SET (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,noexecstack")
diff --git a/src/netlink/audit-rule.cpp b/src/netlink/audit-rule.cpp
new file mode 100644 (file)
index 0000000..6a5fdda
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ *  Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+#include <klay/error.h>
+#include <klay/exception.h>
+
+#include <klay/netlink/audit-rule.h>
+
+namespace netlink {
+
+AuditRule::AuditRule() :
+       buf(sizeof(struct audit_rule_data))
+{
+       auto r = (struct audit_rule_data *)buf.data();
+       r->flags = AUDIT_FILTER_EXIT;
+       r->action = AUDIT_ALWAYS;
+}
+
+AuditRule::AuditRule(std::vector<char> &buf) :
+       buf(buf)
+{
+
+}
+
+AuditRule::~AuditRule()
+{
+
+}
+
+void AuditRule::setSystemCall(unsigned int syscall)
+{
+       auto r = (struct audit_rule_data *)buf.data();
+       r->mask[syscall / 32] |= 1 << (syscall % 32);
+}
+
+void AuditRule::unsetSystemCall(unsigned int syscall)
+{
+       auto r = (struct audit_rule_data *)buf.data();
+       r->mask[syscall / 32] &= ~(1 << (syscall % 32));
+}
+
+void AuditRule::setAllSystemCalls()
+{
+       auto r = (struct audit_rule_data *)buf.data();
+       for (auto &m : r->mask) {
+               m = 0xffffffff;
+       }
+}
+
+void AuditRule::clearAllSystemCalls()
+{
+       auto r = (struct audit_rule_data *)buf.data();
+       for (auto &m : r->mask) {
+               m = 0;
+       }
+}
+
+std::vector<unsigned int> AuditRule::getSystemCalls() const
+{
+       auto r = (struct audit_rule_data *)buf.data();
+       std::vector<unsigned int> ret;
+
+       for (int i = 0; i < AUDIT_BITMASK_SIZE; i++) {
+               for (int j = 0, k = 1; j < 32; j++, k <<= 1) {
+                       if (r->mask[i] & k) {
+                               ret.push_back(i << 5 | j);
+                       }
+               }
+       }
+       return ret;
+}
+
+void AuditRule::setReturn(unsigned int val)
+{
+       auto r = (struct audit_rule_data *)buf.data();
+       unsigned int i;
+
+       for (i = 0; i < r->field_count; i++) {
+               if (r->fields[i] == AUDIT_EXIT) {
+                       break;
+               }
+       }
+       if (i == r->field_count) {
+               r->fields[i] = AUDIT_EXIT;
+               r->fieldflags[i] = AUDIT_EQUAL;
+               r->field_count++;
+       }
+       r->values[i] = val;
+}
+
+void AuditRule::unsetReturn()
+{
+       auto r = (struct audit_rule_data *)buf.data();
+       unsigned int i;
+
+       for (i = 0; i < r->field_count; i++) {
+               if (r->fields[i] == AUDIT_EXIT) {
+                       break;
+               }
+       }
+
+       if (i == r->field_count) {
+               return;
+       }
+
+       std::move(&r->values[i + 1], &r->values[r->field_count], &r->values[i]);
+       std::move(&r->fields[i + 1], &r->fields[r->field_count], &r->fields[i]);
+       std::move(&r->fieldflags[i + 1], &r->fieldflags[r->field_count], &r->fieldflags[i]);
+
+       r->field_count--;
+
+       r->values[r->field_count] = 0;
+       r->fields[r->field_count] = 0;
+       r->fieldflags[r->field_count] = 0;
+}
+
+unsigned int AuditRule::getReturn() const
+{
+       auto r = (struct audit_rule_data *)buf.data();
+       for (unsigned int i = 0; i < r->field_count; i++) {
+               if (r->fields[i] == AUDIT_EXIT) {
+                       return r->values[i];
+               }
+       }
+       throw runtime::Exception("No rule for return");
+}
+
+bool AuditRule::hasReturn() const
+{
+       auto r = (struct audit_rule_data *)buf.data();
+       for (unsigned int i = 0; i < r->field_count; i++) {
+               if (r->fields[i] == AUDIT_EXIT) {
+                       return true;
+               }
+       }
+       return false;
+}
+
+void AuditRule::setKey(const std::string &name)
+{
+       auto r = (struct audit_rule_data *)buf.data();
+       unsigned int i;
+
+       for (i = 0; i < r->field_count; i++) {
+               if (r->fields[i] == AUDIT_FILTERKEY) {
+                       break;
+               }
+       }
+
+       if (i == r->field_count) {
+               r->fields[i] = AUDIT_FILTERKEY;
+               r->fieldflags[i] = AUDIT_EQUAL;
+               r->field_count++;
+       }
+
+       // TODO : Calculate the offset. It assummed that there is no field to use buffer
+
+       r->values[i] = name.size();
+       r->buflen = name.size();
+
+       buf.resize(sizeof(struct audit_rule_data) + name.size());
+       r = (struct audit_rule_data *)buf.data();
+       std::copy(name.begin(), name.end(), r->buf);
+}
+
+void AuditRule::unsetKey()
+{
+       auto r = (struct audit_rule_data *)buf.data();
+       unsigned int i;
+
+       for (i = 0; i < r->field_count; i++) {
+               if (r->fields[i] == AUDIT_FILTERKEY) {
+                       break;
+               }
+       }
+
+       if (i == r->field_count) {
+               return;
+       }
+
+       std::move(&r->values[i + 1], &r->values[r->field_count], &r->values[i]);
+       std::move(&r->fields[i + 1], &r->fields[r->field_count], &r->fields[i]);
+       std::move(&r->fieldflags[i + 1], &r->fieldflags[r->field_count], &r->fieldflags[i]);
+
+       r->field_count--;
+
+       r->values[r->field_count] = 0;
+       r->fields[r->field_count] = 0;
+       r->fieldflags[r->field_count] = 0;
+}
+
+const std::string AuditRule::getkey() const
+{
+       auto r = (struct audit_rule_data *)buf.data();
+       for (unsigned int i = 0; i < r->field_count; i++) {
+               if (r->fields[i] == AUDIT_FILTERKEY) {
+                       // TODO : Calculate the offset. It assummed that there is no field to use buffer
+                       return r->buf;
+               }
+       }
+
+       throw runtime::Exception("No rule for key");
+}
+
+bool AuditRule::hasKey() const
+{
+       auto r = (struct audit_rule_data *)buf.data();
+       for (unsigned int i = 0; i < r->field_count; i++) {
+               if (r->fields[i] == AUDIT_FILTERKEY) {
+                       return true;
+               }
+       }
+       return false;
+}
+
+} // namespace runtime
index 680656ea02f48a652bc501ce58ce15be2868e396..58689b7b5344a815df0dc41128af7558d631f5ea 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -13,8 +13,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License
  */
-#include <iostream>
-
 #include <poll.h>
 #include <fcntl.h>
 #include <unistd.h>
@@ -95,6 +93,41 @@ int Audit::isEnabled()
        return ret;
 }
 
+std::vector<AuditRule> Audit::getRules()
+{
+       std::vector<AuditRule> ret;
+
+       send(AUDIT_LIST_RULES, NULL, 0);
+
+       while (1) {
+               auto msg = recv();
+
+               switch (msg.first) {
+               case NLMSG_DONE:
+                       break;
+               case NLMSG_ERROR:
+                       throw runtime::Exception("Failed to get a list of audit rules");
+               case AUDIT_LIST_RULES:
+                       ret.push_back(msg.second);
+               default:
+                       continue;
+               }
+
+               break;
+       }
+       return ret;
+}
+
+void Audit::addRule(const AuditRule& rule)
+{
+       send(AUDIT_ADD_RULE, rule.data(), rule.size());
+}
+
+void Audit::removeRule(const AuditRule& rule)
+{
+       send(AUDIT_DEL_RULE, rule.data(), rule.size());
+}
+
 void Audit::setMainloop(runtime::Mainloop *ml)
 {
        int fd = nl.getFd();
@@ -132,10 +165,11 @@ void Audit::send(int type, const void *data, unsigned int size)
                ::memcpy(NLMSG_DATA(buf), data, size);
        }
 
-       nl.send(&buf, sizeof(buf));
+       nl.send(buf, sizeof(buf));
 
        if (recv(MSG_PEEK).first == NLMSG_ERROR) {
-               auto err = (struct nlmsgerr*)recv().second.data();
+               auto reply = recv().second;
+               auto err = (struct nlmsgerr*)reply.data();
                if (err->error) {
                        throw runtime::Exception("Audit netlink error: " +
                                                                                std::to_string(err->error));
index c0bf91a62db5dc5962664f14d2bc72cc1d232517..9f4fdd789a5df7c39f0596459db2d8c668c25c65 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -64,7 +64,7 @@ void Netlink::send(const void *buf, unsigned int size)
 
        do {
                ret = ::sendto(fd, buf, size, 0,
-                                               (struct sockaddr*)&addr, size);
+                                               (struct sockaddr*)&addr, sizeof(addr));
        } while (ret < 0 && errno == EINTR);
 
        if (ret < 0) {