--- /dev/null
+/*
+ * 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__*/
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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__*/
--- /dev/null
+/*
+ * 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__*/
--- /dev/null
+/*
+ * 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__*/