From: Sungbae Yoo Date: Fri, 30 Jun 2017 11:59:12 +0000 (+0900) Subject: Add the management of audit rules in netlink audit X-Git-Tag: submit/tizen/20170720.071940~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F41%2F136641%2F4;p=platform%2Fcore%2Fsecurity%2Fklay.git Add the management of audit rules in netlink audit Signed-off-by: Sungbae Yoo Change-Id: I22f2c5c44015d8dc57b97e69d87413ea2e06c1fa --- diff --git a/include/klay/netlink/audit-rule.h b/include/klay/netlink/audit-rule.h new file mode 100644 index 0000000..16faaad --- /dev/null +++ b/include/klay/netlink/audit-rule.h @@ -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 + +#include + +namespace netlink { + +class AuditRule final { +public: + AuditRule(); + AuditRule(std::vector& buf); + ~AuditRule(); + + void setSystemCall(unsigned int syscall); + void unsetSystemCall(unsigned int syscall); + void setAllSystemCalls(); + void clearAllSystemCalls(); + std::vector 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 buf; +}; + +} // namespace runtime + +#endif //!__RUNTIME_NETLINK_AUDIT_RULE_H__ diff --git a/include/klay/netlink/audit.h b/include/klay/netlink/audit.h index 61a2ef6..5098d23 100644 --- a/include/klay/netlink/audit.h +++ b/include/klay/netlink/audit.h @@ -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 #include +#include namespace netlink { @@ -33,16 +34,20 @@ public: typedef std::function 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 getRules(); + void addRule(const AuditRule& rule); + void removeRule(const AuditRule& rule); + void setMainloop(runtime::Mainloop *ml); void setMessageHandler(MessageHandler&& handler); diff --git a/include/klay/netlink/netlink.h b/include/klay/netlink/netlink.h index 10e5a80..0e12e11 100644 --- a/include/klay/netlink/netlink.h +++ b/include/klay/netlink/netlink.h @@ -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); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c135d23..7a15c38 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 index 0000000..6a5fdda --- /dev/null +++ b/src/netlink/audit-rule.cpp @@ -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 +#include + +#include + +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 &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 AuditRule::getSystemCalls() const +{ + auto r = (struct audit_rule_data *)buf.data(); + std::vector 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 diff --git a/src/netlink/audit.cpp b/src/netlink/audit.cpp index 680656e..58689b7 100644 --- a/src/netlink/audit.cpp +++ b/src/netlink/audit.cpp @@ -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 - #include #include #include @@ -95,6 +93,41 @@ int Audit::isEnabled() return ret; } +std::vector Audit::getRules() +{ + std::vector 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)); diff --git a/src/netlink/netlink.cpp b/src/netlink/netlink.cpp index c0bf91a..9f4fdd7 100644 --- a/src/netlink/netlink.cpp +++ b/src/netlink/netlink.cpp @@ -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) {