Add audit class to use linux audit subsystem 58/133758/5 accepted/tizen/unified/20170726.013003 submit/tizen/20170725.065700 submit/tizen/20170725.091352
authorSungbae Yoo <sungbae.yoo@samsung.com>
Fri, 9 Jun 2017 11:31:50 +0000 (20:31 +0900)
committerSungbae Yoo <sungbae.yoo@samsung.com>
Mon, 26 Jun 2017 11:43:03 +0000 (20:43 +0900)
Signed-off-by: Sungbae Yoo <sungbae.yoo@samsung.com>
Change-Id: I9a88371ebe822c93efd5a849de311d6a8ed4761f

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

diff --git a/include/klay/netlink/audit.h b/include/klay/netlink/audit.h
new file mode 100644 (file)
index 0000000..61a2ef6
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ *  Copyright (c) 2015 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_H__
+#define __RUNTIME_NETLINK_AUDIT_H__
+
+#include <list>
+#include <vector>
+
+#include <linux/audit.h>
+
+#include <klay/mainloop.h>
+#include <klay/netlink/netlink.h>
+
+namespace netlink {
+
+class Audit final {
+public:
+       typedef std::pair<int, std::vector<char>> Message;
+       typedef std::function<void(Message&)> MessageHandler;
+
+       Audit();
+    Audit(Audit&&);
+    Audit(const Audit&) = delete;
+    ~Audit();
+
+    Audit& operator=(const Audit&) = delete;
+
+       void setPID(pid_t pid);
+       void setEnabled(int enabled);
+       int isEnabled();
+
+       void setMainloop(runtime::Mainloop *ml);
+       void setMessageHandler(MessageHandler&& handler);
+
+private:
+       void send(int type, const void *data, unsigned int size);
+       Message recv(int options = 0);
+
+       void processMessage(int fd, runtime::Mainloop::Event event);
+
+       Netlink nl;
+       unsigned int sequence = 0;
+       runtime::Mainloop *mainloop;
+       MessageHandler messageHandler;
+};
+
+} // namespace runtime
+
+#endif //!__RUNTIME_NETLINK_AUDIT_H__
diff --git a/include/klay/netlink/netlink.h b/include/klay/netlink/netlink.h
new file mode 100644 (file)
index 0000000..10e5a80
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ *  Copyright (c) 2015 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_NETLINK_H__
+#define __RUNTIME_NETLINK_NETLINK_H__
+
+#include <linux/netlink.h>
+
+#ifndef NETLINK_AUDIT
+#define NETLINK_AUDIT 9
+#endif
+
+namespace netlink {
+
+class Netlink final {
+public:
+       Netlink(int);
+    Netlink(Netlink&&);
+    Netlink(const Netlink&) = delete;
+    ~Netlink();
+
+    Netlink& operator=(const Netlink&) = delete;
+
+       void send(const void *data, unsigned int size);
+       void recv(void *data, unsigned int size, int options = 0);
+
+       int getFd() const {
+               return fd;
+       }
+
+private:
+       int fd;
+};
+
+} // namespace runtime
+
+#endif //!__RUNTIME_NETLINK_NETLINK_H__
index 883b63b9fdd3558f07e96e4637098765f7f8c708..77d33d3b2b0ce95b3a9b189359602a4fb89696ce 100644 (file)
@@ -187,6 +187,8 @@ public:
                return processingContext.credentials.gid;
        }
 
+       runtime::Mainloop mainloop;
+
 private:
        struct ProcessingContext {
                ProcessingContext() = default;
@@ -229,7 +231,6 @@ private:
        NotificationRegistry notificationRegistry;
        ConnectionRegistry connectionRegistry;
 
-       runtime::Mainloop mainloop;
        std::string address;
 
        runtime::ThreadPool workqueue;
index a1fb0bc5021569bb68141566ad9dcae3e50f5c19..c135d233b980821f16070db5bfb4abb54d05f98b 100755 (executable)
@@ -48,6 +48,8 @@ SET (KLAY_SOURCES             ${KLAY_SRC}/error.cpp
                                                ${KLAY_SRC}/audit/console-sink.cpp
                                                ${KLAY_SRC}/audit/dlog-sink.cpp
                                                ${KLAY_SRC}/audit/audit-trail.cpp
+                                               ${KLAY_SRC}/netlink/audit.cpp
+                                               ${KLAY_SRC}/netlink/netlink.cpp
 )
 
 SET (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,noexecstack")
diff --git a/src/netlink/audit.cpp b/src/netlink/audit.cpp
new file mode 100644 (file)
index 0000000..680656e
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ *  Copyright (c) 2015 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 <iostream>
+
+#include <poll.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/socket.h>
+
+#include <cstring>
+
+#include <klay/error.h>
+#include <klay/exception.h>
+
+#include <klay/netlink/audit.h>
+
+using namespace std::placeholders;
+
+namespace netlink {
+
+Audit::Audit() :
+       nl(NETLINK_AUDIT), sequence(0), mainloop(nullptr)
+{
+
+}
+
+Audit::Audit(Audit&& audit) :
+       nl(std::move(audit.nl)), sequence(audit.sequence), mainloop(audit.mainloop)
+{
+
+}
+
+Audit::~Audit()
+{
+
+}
+
+void Audit::setPID(pid_t pid)
+{
+       struct audit_status s;
+
+       ::memset(&s, 0, sizeof(s));
+       s.mask  = AUDIT_STATUS_PID;
+       s.pid   = pid;
+
+       send(AUDIT_SET, &s, sizeof(s));
+}
+
+void Audit::setEnabled(int enabled)
+{
+       struct audit_status s;
+
+       ::memset(&s, 0, sizeof(s));
+       s.mask          = AUDIT_STATUS_ENABLED;
+       s.enabled       = enabled;
+
+       send(AUDIT_SET, &s, sizeof(s));
+}
+
+int Audit::isEnabled()
+{
+       int ret = 0;
+       send(AUDIT_GET, NULL, 0);
+
+       while (1) {
+               auto msg = recv();
+
+               switch (msg.first) {
+               case NLMSG_DONE:
+               case NLMSG_ERROR:
+                       throw runtime::Exception("Failed to get audit state");
+               case AUDIT_GET:
+                       ret = ((struct audit_status*)msg.second.data())->enabled;
+                       break;
+               default:
+                       continue;
+               }
+
+               break;
+       }
+
+       return ret;
+}
+
+void Audit::setMainloop(runtime::Mainloop *ml)
+{
+       int fd = nl.getFd();
+
+       if (mainloop != nullptr) {
+               mainloop->removeEventSource(fd);
+       }
+       mainloop = ml;
+       mainloop->addEventSource(fd, POLLIN, std::bind(&Audit::processMessage,
+                                                                                                       this, _1, _2));
+}
+
+void Audit::setMessageHandler(MessageHandler&& handler)
+{
+       messageHandler = handler;
+}
+
+void Audit::send(int type, const void *data, unsigned int size)
+{
+       char buf[NLMSG_SPACE(size)];
+       auto *nlh = (struct nlmsghdr *)buf;
+
+       ::memset(buf, 0, sizeof(buf));
+
+       nlh->nlmsg_len = sizeof(buf);
+       nlh->nlmsg_type = type;
+       nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+       nlh->nlmsg_seq = ++sequence;
+
+       if (sequence == 0) {
+               sequence++;
+       }
+
+       if (size && data) {
+               ::memcpy(NLMSG_DATA(buf), data, size);
+       }
+
+       nl.send(&buf, sizeof(buf));
+
+       if (recv(MSG_PEEK).first == NLMSG_ERROR) {
+               auto err = (struct nlmsgerr*)recv().second.data();
+               if (err->error) {
+                       throw runtime::Exception("Audit netlink error: " +
+                                                                               std::to_string(err->error));
+               }
+       }
+}
+
+Audit::Message Audit::recv(int options)
+{
+       struct nlmsghdr nlh;
+
+       processMessage(nl.getFd(), POLLIN);
+
+       //To get message size
+       nl.recv(&nlh, sizeof(nlh), options | MSG_PEEK);
+
+       char buf[nlh.nlmsg_len + NLMSG_HDRLEN];
+       nl.recv(buf, sizeof(buf), options);
+
+       Message msg = {nlh.nlmsg_type, std::vector<char>(nlh.nlmsg_len)};
+
+       ::memcpy(msg.second.data(), NLMSG_DATA(buf), msg.second.size());
+       return msg;
+}
+
+void Audit::processMessage(int fd, runtime::Mainloop::Event event)
+{
+       struct nlmsghdr nlh;
+
+       nl.recv(&nlh, sizeof(nlh), MSG_PEEK);
+
+       while (nlh.nlmsg_seq == 0) {
+               char buf[nlh.nlmsg_len + NLMSG_HDRLEN];
+               nl.recv(buf, sizeof(buf));
+
+               Message msg = {nlh.nlmsg_type, std::vector<char>(nlh.nlmsg_len)};
+
+               ::memcpy(msg.second.data(), NLMSG_DATA(buf), msg.second.size());
+               if (messageHandler) {
+                       messageHandler(msg);
+               }
+
+               try {
+                       nl.recv(&nlh, sizeof(nlh), MSG_PEEK | MSG_DONTWAIT);
+               } catch (runtime::Exception &e) {
+                       break;
+               }
+       }
+}
+
+} // namespace runtime
diff --git a/src/netlink/netlink.cpp b/src/netlink/netlink.cpp
new file mode 100644 (file)
index 0000000..c0bf91a
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ *  Copyright (c) 2015 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 <fcntl.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+
+#include <cstring>
+
+#include <klay/error.h>
+#include <klay/exception.h>
+#include <klay/netlink/netlink.h>
+
+namespace netlink {
+
+Netlink::Netlink(int protocol)
+{
+       fd = ::socket(PF_NETLINK, SOCK_RAW, protocol);
+       if (fd < 0) {
+               throw runtime::Exception(runtime::GetSystemErrorMessage());
+       }
+
+       if (::fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
+               ::close(fd);
+               throw runtime::Exception(runtime::GetSystemErrorMessage());
+       }
+}
+
+Netlink::Netlink(Netlink&& netlink) :
+       fd(netlink.fd)
+{
+       netlink.fd = -1;
+}
+
+Netlink::~Netlink()
+{
+       if (fd > 0) {
+               ::close(fd);
+       }
+}
+
+void Netlink::send(const void *buf, unsigned int size)
+{
+       struct sockaddr_nl addr;
+       int ret;
+
+       ::memset(&addr, 0, sizeof(addr));
+       addr.nl_family = AF_NETLINK;
+       addr.nl_pid = 0;
+       addr.nl_groups = 0;
+
+       do {
+               ret = ::sendto(fd, buf, size, 0,
+                                               (struct sockaddr*)&addr, size);
+       } while (ret < 0 && errno == EINTR);
+
+       if (ret < 0) {
+               throw runtime::Exception("Failed to send audit packet");
+       }
+}
+
+void Netlink::recv(void *buf, unsigned int size, int options)
+{
+       struct sockaddr_nl nladdr;
+       socklen_t nladdrlen = sizeof(nladdr);
+       int ret;
+
+       do {
+               ret = ::recvfrom(fd, buf, size, options,
+                                                       (struct sockaddr*)&nladdr, &nladdrlen);
+       } while (ret < 0 && errno == EINTR);
+
+       if (ret < 0) {
+               throw runtime::Exception("Failed to receive audit packet");
+       }
+
+       if (nladdrlen != sizeof(nladdr)) {
+               throw runtime::Exception("Bad address size reading audit netlink socket");
+       }
+
+       if (nladdr.nl_pid) {
+               throw runtime::Exception("Spoofed packet received on audit netlink socket");
+       }
+}
+
+} // namespace runtime