--- /dev/null
+/*
+ * 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__
--- /dev/null
+/*
+ * 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__
return processingContext.credentials.gid;
}
+ runtime::Mainloop mainloop;
+
private:
struct ProcessingContext {
ProcessingContext() = default;
NotificationRegistry notificationRegistry;
ConnectionRegistry connectionRegistry;
- runtime::Mainloop mainloop;
std::string address;
runtime::ThreadPool workqueue;
${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")
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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