[POLICYREP] Add tunable support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch adds support for tunables to the policy language.  It is
based on the existing boolean support.

Signed-Off-By: Todd C. Miller <tmiller@xxxxxxxxxx>

Index: libpolicyrep/tests/example.te
===================================================================
--- libpolicyrep/tests/example.te	(revision 2703)
+++ libpolicyrep/tests/example.te	(working copy)
@@ -33,6 +33,9 @@
 
 bool foo true;
 
+tunable bar true;
+tunable baz false;
+
 user foo_u roles bar_r;
 user fooyou_u roles bar_r level s1 range s1:c2 - s12:c3;
 user fubu_u roles bar_r level s1 range s3 - s13:c3,c5,c12.c34;
@@ -60,7 +63,30 @@
 
 optional {
 	 allow method foo : file execute;
+	 iftun (baz) {
+		allow method file : file getattr;
+	 }
 } else {
 	 allow pebenito foo : file execute;
+	 iftun (bar) {
+		allow pebenito file : file getattr;
+	 }
 }
 
+
+iftun (bar) {
+	allow method bar : file execute;
+	iftun (baz) {
+		 allow method bar : file getattr;
+	} else {
+		 allow pebenito bar : file getattr;
+	}
+	optional {
+		 allow method bar : file { read write };
+	} else {
+		 allow pebenito bar : file { read write };
+	}
+} else {
+	allow pebenito bar : file execute;
+}
+
Index: libpolicyrep/include/policyrep/tunable.hpp
===================================================================
--- libpolicyrep/include/policyrep/tunable.hpp	(revision 0)
+++ libpolicyrep/include/policyrep/tunable.hpp	(revision 0)
@@ -0,0 +1,145 @@
+/* Author: Karl MacMillan <kmacmillan@xxxxxxxxxxxxxxxxx> */
+
+#ifndef __tunable_hpp__
+#define __tunable_hpp__
+
+#include <policyrep/policy_base.hpp>
+
+#include <list>
+
+namespace policyrep
+{
+
+	/* Introduction
+	 *
+	 * Tunable policy in policyrep is handled in such a way that
+	 * the normal tree iteration works unchanged all the way to the
+	 * most nested leaf nodes. To achieve this the design is not
+	 * what might be most obvious.
+	 *
+	 * The tunable policy statements:
+	 *
+	 * iftun (foo) {
+	 *     allow foo_t bar_t : file read;
+	 * } else {
+	 *     allow baz_t bar_t : file write;
+	 * }
+	 *
+	 * Are encoded into the following tree struction:
+	 *
+	 * TunableBlock
+	 *     TunableBranch (with TunableExpr foo)
+	 *          AVRule
+	 *     TunableBranch (with else == true)
+	 *          AVRule
+	 *
+	 * The TunableBranches are just children of the TunableBlock,
+	 * but the TunableBlock has an overloaded add_child implementation
+	 * to prevent more than two children from being added.
+	 */
+
+	struct TunableBoolImpl;
+	class TunableBool : public Node
+	{
+	public:
+		TunableBool();
+		TunableBool(const std::string& name, bool v);
+		TunableBool(const TunableBool& other);
+		virtual ~TunableBool();
+		virtual void operator=(const TunableBool& other);
+
+		virtual void set_name(const std::string& name);
+		virtual const std::string& get_name() const;
+
+		virtual void set_default_value(bool v);
+		virtual bool get_default_value() const;
+	protected:
+		void copy(const TunableBool& other);
+		virtual void do_output(std::ostream& o, const OutputFormatter& op) const;
+		TunableBoolImpl* impl;
+	};
+
+	class TunableOp;
+	std::ostream& operator<<(std::ostream& o, const TunableOp& op);
+
+	//
+	// TunableOp
+	//
+
+	struct TunableOpImpl;
+	class TunableOp
+	{
+	public:
+		enum Op { BOOL, NOT, OR, AND, XOR, EQ, NEQ };
+		TunableOp();
+		TunableOp(const std::string& b);
+		TunableOp(Op op);
+		TunableOp(const TunableOp& other);
+		virtual ~TunableOp();
+		virtual void operator=(const TunableOp& other);
+
+		virtual void set_op(Op op);
+		virtual Op get_op() const;
+
+		/* changes op to BOOL in addition to setting the tunable */
+		virtual void set_tunable(const std::string& b);
+		virtual const std::string& get_tunable() const;
+		friend std::ostream& operator<<(std::ostream& o, const TunableOp& op);
+
+	protected:
+		TunableOpImpl* impl;
+	};
+
+	//
+	// TunableExpr
+	//
+
+	typedef std::list<TunableOp> TunableExpr;
+
+	// forward declarations
+
+	class TunableBranch;
+	typedef boost::shared_ptr<TunableBranch> TunableBranchPtr;
+
+	//
+	// TunableBlock
+	//
+
+	struct TunableBlockImpl;
+	class TunableBlock : public PolicyBlock
+	{
+	public:
+		TunableBlock();
+		TunableBlock(TunableBranchPtr if_);
+		TunableBlock(TunableBranchPtr if_, TunableBranchPtr else_);
+		TunableBlock(const TunableBlock& other);
+		virtual ~TunableBlock();
+		virtual void operator=(const TunableBlock& other);
+	protected:
+		void copy(const TunableBlock& other);
+		TunableBlockImpl* impl;
+	};
+
+	//
+	// TunableBranch
+	//
+
+	struct TunableBranchImpl;
+	class TunableBranch : public PolicyBranch
+	{
+	public:
+		TunableBranch();
+		TunableBranch(const TunableBranch& other);
+		virtual ~TunableBranch();
+		virtual void operator=(const TunableBranch& other);
+
+		virtual TunableExpr& expr();
+	protected:
+		virtual void do_output(std::ostream& o, const OutputFormatter& op) const;
+		void copy(const TunableBranch& other);
+		TunableBranchImpl* impl;
+	};
+
+} // namespace policyrep
+
+#endif
Index: libpolicyrep/include/policyrep/policy.hpp
===================================================================
--- libpolicyrep/include/policyrep/policy.hpp	(revision 2703)
+++ libpolicyrep/include/policyrep/policy.hpp	(working copy)
@@ -12,6 +12,7 @@
 #include <policyrep/user.hpp>
 #include <policyrep/mls.hpp>
 #include <policyrep/optional.hpp>
+#include <policyrep/tunable.hpp>
 
 namespace policyrep
 {
Index: libpolicyrep/src/policy_scan.l
===================================================================
--- libpolicyrep/src/policy_scan.l	(revision 2703)
+++ libpolicyrep/src/policy_scan.l	(working copy)
@@ -92,6 +92,8 @@
 type				{ return token::TYPE; }
 BOOL |
 bool                            { return token::BOOL; }
+TUNABLE |
+tunable                         { return token::TUNABLE; }
 IF |
 if				{ return token::IF; }
 ELSE |
@@ -145,6 +147,7 @@
 module|MODULE                   { return token::MODULE; }
 require|REQUIRE                 { return token::REQUIRE; }
 optional|OPTIONAL               { return token::OPTIONAL; }
+iftun|IFTUN                     { return token::IFTUN; }
 OR |
 or     			        { return token::OR;}
 AND |
Index: libpolicyrep/src/policy_parse.y
===================================================================
--- libpolicyrep/src/policy_parse.y	(revision 2703)
+++ libpolicyrep/src/policy_parse.y	(working copy)
@@ -85,6 +85,8 @@
 	CondExpr* cond_expr;
 	CondBranch* cond_branch;
 	OptionalBranch* optional_branch;
+	TunableExpr* tunable_expr;
+	TunableBranch* tunable_branch;
 	bool bval;
 }
 
@@ -139,6 +141,9 @@
 %type <pnode> bool_def
 %type <pnode> optional_block_def
 %type <pnode> optional_statement
+%type <pnode> tunable_def
+%type <pnode> tunable_block_def
+%type <pnode> tunable_statement
 
 
 %type <cond_branch> cond_else
@@ -146,10 +151,16 @@
 
 %type <optional_branch> optional_statements
 
+%type <tunable_branch> tunable_statements
+
 %type <cond_expr> cond_expr
 
+%type <tunable_expr> tunable_expr
+
 %type <bval> bool_val
 
+%type <bval> tunable_val
+
 %token END 0
 %token <id> PATH
 %token CLONE
@@ -168,6 +179,8 @@
 %token ALIAS
 %token ATTRIBUTE
 %token BOOL
+%token TUNABLE
+%token IFTUN
 %token IF
 %token ELSE
 %token TYPE_TRANSITION
@@ -277,6 +290,9 @@
 			| cond_block_def
 			/* optional policy */
 			| optional_block_def
+			/* tunable policy */
+			| tunable_def
+			| tunable_block_def
 			;
 ignored_policy_statement: require_block
 			;
@@ -468,7 +484,80 @@
 			| bool_def
 			| cond_block_def
 			/* optional policy */
+			| optional_block_def
+			/* tunable policy */
+			| tunable_def
+			| tunable_block_def
 			;
+tunable_def		: TUNABLE IDENTIFIER tunable_val SEMI
+			  { $$ = new TunableBool(*$2, $3); delete $2; }
+			;
+tunable_val		: CTRUE { $$ = true; }
+			| CFALSE { $$ = false; }
+			;
+tunable_block_def	: IFTUN tunable_expr LBRACE tunable_statements RBRACE ELSE LBRACE tunable_statements RBRACE
+			  { $4->expr() = *$2; delete $2; $$ = new TunableBlock(TunableBranchPtr($4), TunableBranchPtr($8)); }
+			| IFTUN tunable_expr LBRACE tunable_statements RBRACE
+			  { $4->expr() = *$2; delete $2; $$ = new TunableBlock(TunableBranchPtr($4)); }
+			;
+tunable_expr		: LPAREN tunable_expr RPAREN
+			  { $$ = $2; }
+			| NOT tunable_expr
+			  { $2->push_front(TunableOp(TunableOp::NOT)); $$ = $2; }
+			| tunable_expr AND tunable_expr
+			  { $1->push_back(TunableOp(TunableOp::AND));
+			    $1->insert($1->end(), $3->begin(), $3->end());
+			    $$ = $1; }
+			| tunable_expr OR tunable_expr
+			  { $1->push_back(TunableOp(TunableOp::OR));
+			    $1->insert($1->end(), $3->begin(), $3->end());
+			    $$ = $1; }
+			| tunable_expr XOR tunable_expr
+			  { $1->push_back(TunableOp(TunableOp::XOR));
+			    $1->insert($1->end(), $3->begin(), $3->end());
+			    $$ = $1; }
+			| tunable_expr EQUALS tunable_expr
+			  { $1->push_back(TunableOp(TunableOp::EQ));
+			    $1->insert($1->end(), $3->begin(), $3->end());
+			    $$ = $1; }
+			| tunable_expr NOTEQUAL tunable_expr
+			  { $1->push_back(TunableOp(TunableOp::NEQ));
+			    $1->insert($1->end(), $3->begin(), $3->end());
+			    $$ = $1; }
+			| IDENTIFIER
+			  { $$ = new TunableExpr(); $$->push_back(TunableOp(*$1)); delete $1; }
+			;
+tunable_statements	: tunable_statement
+			  { TunableBranch* b = new TunableBranch; b->append_child(NodePtr($1)); $$ = b; }
+			| ignored_policy_statement
+			  { $$ = new TunableBranch; }
+			| tunable_statement tunable_statements
+			  { $2->append_child(NodePtr($1)); $$ = $2; }
+			| ignored_policy_statement tunable_statements
+			  { $$ = $2; }
+			;
+tunable_statement       : class_def
+			/* TE decl */
+			| attribute_def
+			| type_def
+			| typealias_def
+			| typeattribute_def
+			/* rules */
+			| allow_def
+			| auditallow_def
+			| auditdeny_def
+			| dontaudit_def
+			| neverallow_def
+			| transition_def
+			/* conditional policy */
+			| bool_def
+			| cond_block_def
+			/* optional policy */
+			| optional_block_def
+			/* tunable policy */
+			| tunable_def
+			| tunable_block_def
+			;
 transition_def		: TYPE_TRANSITION names names COLON names IDENTIFIER SEMI
 			  { $$ = define_typerule(TypeRule::TRANSITION, $2, $3, $5, $6, driver); }
                         | TYPE_MEMBER names names COLON names IDENTIFIER SEMI
Index: libpolicyrep/src/tunable.cpp
===================================================================
--- libpolicyrep/src/tunable.cpp	(revision 0)
+++ libpolicyrep/src/tunable.cpp	(revision 0)
@@ -0,0 +1,306 @@
+/*
+ * Author : Karl MacMillan <kmacmillan@xxxxxxxxxxxxxxxxx>
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <policyrep/tunable.hpp>
+#include "policy_base_internal.hpp"
+
+#include <list>
+#include <stdexcept>
+
+namespace policyrep
+{
+	//
+	// TunableBool
+	//
+
+	struct TunableBoolImpl
+	{
+		std::string name;
+		bool default_value;
+	};
+
+	TunableBool::TunableBool() : impl(new TunableBoolImpl)
+	{
+
+	}
+
+	TunableBool::TunableBool(const std::string& name, bool v)
+		: impl(new TunableBoolImpl)
+	{
+		impl->name = name;
+		impl->default_value = v;
+	}
+
+	TunableBool::TunableBool(const TunableBool& other) : Node(), impl(new TunableBoolImpl)
+	{
+		copy(other);
+	}
+
+	TunableBool::~TunableBool()
+	{
+		delete impl;
+	}
+
+	void TunableBool::operator=(const TunableBool& other)
+	{
+		copy(other);
+	}
+
+	void TunableBool::set_name(const std::string& name)
+	{
+		impl->name = name;
+	}
+
+	const std::string& TunableBool::get_name() const
+	{
+		return impl->name;
+	}
+
+	void TunableBool::set_default_value(bool v)
+	{
+		impl->default_value = v;
+	}
+
+	bool TunableBool::get_default_value() const
+	{
+		return impl->default_value;
+	}
+
+	void TunableBool::do_output(std::ostream& o, const OutputFormatter& op) const
+	{
+		o << "tunable " << impl->name << " ";
+		if (impl->default_value)
+			o << "true;";
+		else
+			o << "false;";
+	}
+
+	void TunableBool::copy(const TunableBool& other)
+	{
+		Node::copy(other);
+		*impl = *other.impl;
+	}
+
+	//
+	// TunableOp
+	//
+
+	struct TunableOpImpl
+	{
+		TunableOpImpl() : op(TunableOp::AND) { }
+		TunableOp::Op op;
+		std::string b;
+	};
+
+	TunableOp::TunableOp() : impl(new TunableOpImpl)
+	{
+
+	}
+
+	TunableOp::TunableOp(const std::string& b) : impl(new TunableOpImpl)
+	{
+		impl->op = BOOL;
+		impl->b = b;
+	}
+
+	TunableOp::TunableOp(Op op) : impl(new TunableOpImpl)
+	{
+		impl->op = op;
+	}
+
+	TunableOp::TunableOp(const TunableOp& other) : impl(new TunableOpImpl)
+	{
+		*impl = *other.impl;
+	}
+
+	TunableOp::~TunableOp()
+	{
+		delete impl;
+	}
+
+	void TunableOp::operator=(const TunableOp& other)
+	{
+		*impl = *other.impl;
+	}
+
+	void TunableOp::set_tunable(const std::string& b)
+	{
+		impl->b = b;
+	}
+
+	const std::string& TunableOp::get_tunable() const
+	{
+		return impl->b;
+	}
+
+	void TunableOp::set_op(Op op)
+	{
+		impl->op = op;
+	}
+
+	TunableOp::Op TunableOp::get_op() const
+	{
+		return impl->op;
+	}
+
+	std::ostream& operator<<(std::ostream& o, const TunableOp& op)
+	{
+		switch (op.get_op()) {
+		case TunableOp::BOOL:
+			o << op.get_tunable();
+			break;
+		case TunableOp::NOT:
+			o << "!";
+			break;
+		case TunableOp::OR:
+			o << "|";
+			break;
+		case TunableOp::AND:
+			o << "&";
+			break;
+		case TunableOp::XOR:
+			o << "^";
+			break;
+		case TunableOp::EQ:
+			o << "==";
+			break;
+		case TunableOp::NEQ:
+			o << "!=";
+			break;
+		};
+
+		return o;
+	}
+
+	//
+	// TunableBlock
+	//
+
+	struct TunableBlockImpl { };
+
+	TunableBlock::TunableBlock() : impl(new TunableBlockImpl)
+	{
+
+	}
+
+	TunableBlock::TunableBlock(TunableBranchPtr if_) : impl(new TunableBlockImpl)
+	{
+		append_child(if_);
+	}
+
+	TunableBlock::TunableBlock(TunableBranchPtr if_, TunableBranchPtr else_) : impl(new TunableBlockImpl)
+	{
+		append_child(if_);
+		append_child(else_);
+	}
+
+	TunableBlock::TunableBlock(const TunableBlock& other) : PolicyBlock(), impl(new TunableBlockImpl)
+	{
+		copy(other);
+	}
+
+	TunableBlock::~TunableBlock()
+	{
+		delete impl;
+	}
+
+	void TunableBlock::operator=(const TunableBlock& other)
+	{
+		copy(other);
+	}
+
+	void TunableBlock::copy(const TunableBlock& other)
+	{
+		PolicyBlock::copy(other);
+		*impl = *other.impl;
+	}
+
+
+	//
+	// TunableBranch
+	//
+
+	struct TunableBranchImpl
+	{
+		TunableExpr expr;
+	};
+
+	TunableBranch::TunableBranch() : impl(new TunableBranchImpl)
+	{
+
+	}
+
+	TunableBranch::TunableBranch(const TunableBranch& other) : PolicyBranch(), impl(new TunableBranchImpl)
+	{
+		copy(other);
+	}
+
+	TunableBranch::~TunableBranch()
+	{
+		delete impl;
+	}
+
+	void TunableBranch::operator=(const TunableBranch& other)
+	{
+		copy(other);
+	}
+
+	TunableExpr& TunableBranch::expr()
+	{
+		return impl->expr;
+	}
+
+	void TunableBranch::do_output(std::ostream& o, const OutputFormatter& op) const
+	{
+		if (op.get_end()) {
+			o << "}";
+		} else {
+			if (get_isfalse()) {
+				o << "else {";
+			} else {
+				o << "iftun (";
+				
+				TunableExpr::iterator i, end;
+				i = impl->expr.begin();
+				end = impl->expr.end();
+				bool first = true;
+			
+				for (; i != end; ++i) {
+					if (first)
+						first = false;
+					else
+						o << " ";
+					
+					o << *i;
+				}
+				
+				o << ") {";
+			}
+		}
+
+	}
+
+	void TunableBranch::copy(const TunableBranch& other)
+	{
+		PolicyBranch::copy(other);
+		*impl = *other.impl;
+	}
+
+}

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@xxxxxxxxxxxxx with
the words "unsubscribe selinux" without quotes as the message.

[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux