Add audit rule presentation logic 64/174964/21
authorseolheui kim <s414.kim@samsung.com>
Thu, 5 Apr 2018 11:13:01 +0000 (20:13 +0900)
committerseolheui kim <s414.kim@samsung.com>
Fri, 13 Apr 2018 08:01:01 +0000 (17:01 +0900)
- Add Rule and Field to define audit rules
- Add rule formats to make syscall/watch rules

Change-Id: I028ad2abbe604e779d1c2c337d06f6f891452eaa
Signed-off-by: seolheui kim <s414.kim@samsung.com>
lib/rule/field.h [new file with mode: 0644]
lib/rule/rule.cpp [new file with mode: 0644]
lib/rule/rule.h [new file with mode: 0644]
lib/rule/syscall-rule.h [new file with mode: 0644]
lib/rule/watch-rule.h [new file with mode: 0644]

diff --git a/lib/rule/field.h b/lib/rule/field.h
new file mode 100644 (file)
index 0000000..372901f
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ *  Copyright (c) 2018 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 __AUDIT_RULE_FIELD_H__
+#define __AUDIT_RULE_FIELD_H__
+
+#include <linux/audit.h>
+#include <vector>
+
+#define INT_FIELD(name) \
+class name : public Field<int> { \
+public:        \
+       name() : Field(FieldType::name) {} \
+       name(int value) : Field(FieldType::name) { \
+               _value = value; \
+       }       \
+};
+
+#define STR_FIELD(name) \
+class name : public Field<std::string> { \
+public: \
+       name() : Field(FieldType::name) {} \
+       name(std::string value) : Field(FieldType::name) { \
+               _value = value; \
+       }       \
+};
+
+enum class FieldType : unsigned int {
+#if 0
+       EventPid = AUDIT_PID,
+       EventUid = AUDIT_UID,
+       EventEUid = AUDIT_EUID,
+       EventGid = AUDIT_GID,
+       EventEGid = AUDIT_EGID,
+       EventPPid = AUDIT_PPID,
+       AuditUid = AUDIT_LOGINUID,
+#endif
+       Permission = AUDIT_PERM,
+       WatchPath = AUDIT_WATCH,
+       WatchDir = AUDIT_DIR,
+
+       Arg0 = AUDIT_ARG0,
+       Arg1 = AUDIT_ARG1,
+       Arg2 = AUDIT_ARG2,
+       Arg3 = AUDIT_ARG3,
+
+       Arch = AUDIT_ARCH,
+       Tag = AUDIT_FILTERKEY,
+};
+
+enum class Operator : unsigned int {
+       Equal = AUDIT_EQUAL,
+       NotEqual = AUDIT_NOT_EQUAL,
+       LessThan = AUDIT_LESS_THAN,
+       GreaterThan = AUDIT_GREATER_THAN,
+       LessThanEqual = AUDIT_LESS_THAN_OR_EQUAL,
+       GreaterThanEqual = AUDIT_GREATER_THAN_OR_EQUAL,
+       //BitMask = AUDIT_BIT_MASK,
+       //BitTest = AUDIT_BIT_TEST,
+};
+
+class FieldBase {
+public:
+       virtual void emit(std::vector<char> &rule) = 0;
+       virtual unsigned int type() = 0;
+};
+
+template <typename T>
+class Field : public FieldBase {
+public:
+       using RuleData = struct audit_rule_data;
+
+       Field(FieldType type)
+               : _type(static_cast<unsigned int>(type))
+       {
+       }
+       /* TODO: to be removed below constructor */
+       Field(unsigned int type, unsigned int op, T value)
+               : _type(type), _op(op), _value(value)
+       {
+       }
+       virtual ~Field()
+       {
+       }
+
+       unsigned int type()
+       {
+               return _type;
+       }
+
+       Field &&operator == (T value) {
+               return create(value, Operator::Equal);
+       }
+
+       Field &&operator != (T value) {
+               return create(value, Operator::NotEqual);
+       }
+
+       Field &&operator < (T value) {
+               return create(value, Operator::LessThan);
+       }
+
+       Field &&operator <= (T value) {
+               return create(value, Operator::LessThanEqual);
+       }
+
+       Field &&operator > (T value) {
+               return create(value, Operator::GreaterThan);
+       }
+
+       Field &&operator >= (T value) {
+               return create(value, Operator::GreaterThanEqual);
+       }
+
+       void emit(std::vector<char> &rule) {
+               auto r = reinterpret_cast<RuleData *>(rule.data());
+               r->fields[r->field_count] = _type;
+               r->fieldflags[r->field_count] = _op;
+               setValue(rule, _value);
+       }
+
+private:
+       Field &&create(T value, Operator op) {
+               _op = static_cast<unsigned int>(op);
+               _value = value;
+               return std::move(*this);
+       }
+
+       void setValue(std::vector<char> &rule, int value)
+       {
+               auto r = reinterpret_cast<RuleData *>(rule.data());
+               r->values[r->field_count++] = value;
+       }
+       void setValue(std::vector<char> &rule, const std::string &value)
+       {
+               auto r = reinterpret_cast<RuleData *>(rule.data());
+               r->values[r->field_count] = value.size();
+               rule.resize(sizeof(RuleData) + r->buflen + r->values[r->field_count]);
+
+               r = reinterpret_cast<RuleData *>(rule.data());
+               std::copy(value.begin(), value.end(), r->buf + r->buflen);
+               r->buflen += r->values[r->field_count++];
+       }
+
+protected:
+       unsigned int _type;
+       unsigned int _op;
+       T _value;
+};
+
+INT_FIELD(Permission)
+STR_FIELD(WatchPath)
+STR_FIELD(Tag)
+
+#endif /*__AUDIT_RULE_FIELD_H__*/
diff --git a/lib/rule/rule.cpp b/lib/rule/rule.cpp
new file mode 100644 (file)
index 0000000..a21fd3d
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ *  Copyright (c) 2018 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 "rule.h"
+
+Rule::Rule(RuleType type, Action action, Filter filter)
+       : _type(type), buf(sizeof(RuleData))
+{
+       set(action);
+       set(filter);
+}
+
+Rule::Rule(const std::vector<char> &rule)
+       : _type(RuleType::Default), buf(sizeof(RuleData))
+{
+       setComponents(rule);
+}
+
+Rule::Rule(const Rule &rule)
+       : _type(rule._type), buf(sizeof(RuleData))
+{
+       std::vector<char> bufdata(rule.buf);
+       for (auto &c : rule.conditions) {
+               if (c.second)
+                       c.second->emit(bufdata);
+       }
+       setComponents(bufdata);
+}
+
+Rule::~Rule()
+{
+}
+
+void Rule::setTag(const std::string &tag)
+{
+       //[TODO]: save tags
+       setCondition(Tag(tag));
+}
+
+void Rule::set(Action action)
+{
+       ruleData()->action = underlying_t(action);
+}
+
+void Rule::set(Filter filter)
+{
+       ruleData()->flags = underlying_t(filter);
+}
+
+void Rule::setMask()
+{
+       for (auto &m : ruleData()->mask) {
+               m = ~0;
+       }
+}
+
+void Rule::setMask(unsigned int syscall)
+{
+       int word = AUDIT_WORD(syscall);
+       int bit = AUDIT_BIT(syscall);
+
+       if (word > (AUDIT_BITMASK_SIZE-1))
+               throw runtime::Exception("Invalid syscall number");
+
+       ruleData()->mask[word] |= bit;
+}
+
+void Rule::unsetMask()
+{
+       for (auto &m : ruleData()->mask) {
+               m = 0;
+       }
+}
+
+void Rule::unsetMask(unsigned int syscall)
+{
+       int word = AUDIT_WORD(syscall);
+       int bit = AUDIT_BIT(syscall);
+
+       if (word > (AUDIT_BITMASK_SIZE-1))
+               throw runtime::Exception("Invalid syscall number");
+
+       ruleData()->mask[word] &= ~bit;
+}
+
+std::vector<unsigned int> Rule::getMask()
+{
+       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 (ruleData()->mask[i] & k) {
+                               ret.emplace_back(i << 5 | j);
+                       }
+               }
+       }
+       return ret;
+}
+
+bool Rule::isStringField(unsigned int type)
+{
+       FieldType ftype = static_cast<FieldType>(type);
+       return (ftype == FieldType::WatchPath) ||
+               (ftype == FieldType::Tag) ||
+               (ftype == FieldType::Arch);
+}
+
+void Rule::setComponents(const std::vector<char> &rule)
+{
+       std::vector<char> bufdata(rule);
+       auto r = reinterpret_cast<RuleData *>(bufdata.data());
+       char *ruleBuf = r->buf;
+
+       set(static_cast<Action>(r->action));
+       set(static_cast<Filter>(r->flags));
+
+       for (int i = 0; i < AUDIT_BITMASK_SIZE; i++) {
+               ruleData()->mask[i] = r->mask[i];
+       }
+
+       for (unsigned int i = 0; i < r->field_count; i++) {
+               if (isStringField(r->fields[i])) {
+                       std::string value(ruleBuf, ruleBuf + r->values[i]);
+                       conditions[r->fields[i]].reset(
+                                       new Field<std::string>(r->fields[i], r->fieldflags[i], value));
+                       ruleBuf += r->values[i];
+               } else {
+                       conditions[r->fields[i]].reset(
+                                       new Field<int>(r->fields[i], r->fieldflags[i], r->values[i]));
+               }
+       }
+}
+
+void Rule::updateConditions()
+{
+       for (auto &c : conditions) {
+               if (c.second)
+                       c.second->emit(buf);
+       }
+}
diff --git a/lib/rule/rule.h b/lib/rule/rule.h
new file mode 100644 (file)
index 0000000..1babb4e
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ *  Copyright (c) 2018 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 __AUDIT_RULE_H__
+#define __AUDIT_RULE_H__
+
+#include <unordered_map>
+#include <memory>
+
+#include <linux/audit.h>
+#include <klay/error.h>
+#include <klay/exception.h>
+
+#include "field.h"
+
+enum class Action : unsigned int {
+       Always = AUDIT_ALWAYS,
+       Never = AUDIT_NEVER
+};
+
+enum class Filter : unsigned int {
+       User = AUDIT_FILTER_USER,
+       Exit = AUDIT_FILTER_EXIT,
+       Task = AUDIT_FILTER_TASK,
+       Exclude = AUDIT_FILTER_TYPE,
+};
+
+enum class RuleType {
+       Default,
+       User,
+       Syscall,
+       Watch,
+       Exclude,
+};
+
+class Rule {
+public:
+       using RuleData = struct audit_rule_data;
+
+       Rule(RuleType type = RuleType::Syscall,
+                       Action action = Action::Always, Filter filter = Filter::Exit);
+       virtual ~Rule();
+
+       Rule(Rule &&) = delete;
+       Rule(const std::vector<char> &rule);
+       Rule(const Rule &rule);
+
+       template <typename T>
+       Rule &&operator << (Field<T> &&field)
+       {
+               setCondition(std::move(field));
+               return std::move(*this);
+       }
+
+       bool operator == (const Rule &rule)
+       {
+               return buf == rule.buf;
+       }
+
+       RuleType type()
+       {
+               return _type;
+       }
+
+       void set(RuleType type)
+       {
+               _type = type;
+       }
+       void setTag(const std::string &tag);
+
+       template <typename T>
+       void setCondition(Field<T> &&field);
+       template <typename T>
+       void unsetCondition(Field<T> &&field);
+
+       void setMask();
+       void setMask(unsigned int syscall = 0);
+       void unsetMask();
+       void unsetMask(unsigned int syscall = 0);
+       std::vector<unsigned int> getMask();
+
+protected:
+       void set(Action action);
+       void set(Filter filter);
+
+private:
+       template <typename E>
+       constexpr typename std::underlying_type<E>::type underlying_t(E value) noexcept
+       {
+               return static_cast<typename std::underlying_type<E>::type>(value);
+       }
+
+       RuleData *ruleData()
+       {
+               return reinterpret_cast<RuleData*>(buf.data());
+       }
+       bool isStringField(unsigned int type);
+       void setComponents(const std::vector<char> &rule);
+       void updateConditions();
+private:
+       RuleType _type;
+       std::vector<char> buf;
+       std::unordered_map<unsigned int, std::unique_ptr<FieldBase>> conditions;
+};
+
+template <typename T>
+void Rule::setCondition(Field<T> &&field)
+{
+       conditions[field.type()].reset(new Field<T>(field));
+}
+
+template <typename T>
+void Rule::unsetCondition(Field<T> &&field)
+{
+       if (conditions.find(field.type()) != conditions.end())
+               conditions[field.type()].reset();
+}
+
+#endif /*__AUDIT_RULE_H__*/
diff --git a/lib/rule/syscall-rule.h b/lib/rule/syscall-rule.h
new file mode 100644 (file)
index 0000000..e2ed572
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  Copyright (c) 2018 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 __AUDIT_SYSCALL_RULE_H__
+#define __AUDIT_SYSCALL_RULE_H__
+
+#include "rule.h"
+
+class SyscallRule : public Rule {
+public:
+       SyscallRule(int syscall) {
+               setMask(syscall);
+       }
+       ~SyscallRule() {}
+};
+
+#endif /*__AUDIT_SYSCALL_RULE_H__*/
diff --git a/lib/rule/watch-rule.h b/lib/rule/watch-rule.h
new file mode 100644 (file)
index 0000000..489a235
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ *  Copyright (c) 2018 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 __AUDIT_WATCH_RULE_H__
+#define __AUDIT_WATCH_RULE_H__
+
+#include "rule.h"
+
+class WatchRule : public Rule {
+public:
+       enum Perm {
+               r = AUDIT_PERM_READ,
+               w = AUDIT_PERM_WRITE,
+               x = AUDIT_PERM_EXEC,
+               a = AUDIT_PERM_ATTR,
+       };
+
+       WatchRule(const std::string &path,
+                       unsigned int perm = Perm::r | Perm::w | Perm::x | Perm::a)
+               : Rule(RuleType::Watch)
+       {
+               setCondition(WatchPath(path));
+               setPerm(perm);
+       }
+       ~WatchRule() {}
+
+       void setPerm(unsigned int perm) {
+               setCondition(Permission(perm));
+       }
+};
+
+#endif /*__AUDIT_WATCH_RULE_H__*/