From afeb3561d264566a6803e799517c61a3bbcb23ef Mon Sep 17 00:00:00 2001 From: Chris PeBenito Date: Mon, 11 Jan 2016 14:43:11 -0500 Subject: [PATCH] PolicyDifference: implement genfscon diff Closes #41 --- sediff | 22 ++++++++++ setools/diff/__init__.py | 2 + setools/diff/genfscon.py | 92 ++++++++++++++++++++++++++++++++++++++++ tests/diff.py | 56 ++++++++++++++++++++++++ tests/diff_left.conf | 3 ++ tests/diff_right.conf | 3 ++ 6 files changed, 178 insertions(+) create mode 100644 setools/diff/genfscon.py diff --git a/sediff b/sediff index 8b7a216..025451c 100755 --- a/sediff +++ b/sediff @@ -789,6 +789,28 @@ try: print() + if all_differences or args.genfscon: + if diff.added_genfscons or diff.removed_genfscons or diff.modified_genfscons \ + or args.genfscon: + print("Genfscons ({0} Added, {1} Removed, {2} Modified)".format( + len(diff.added_genfscons), len(diff.removed_genfscons), + len(diff.modified_genfscons))) + if diff.added_genfscons and not args.stats: + print(" Added Genfscons: {0}".format(len(diff.added_genfscons))) + for s in sorted(diff.added_genfscons): + print(" + {0}".format(s)) + if diff.removed_genfscons and not args.stats: + print(" Removed Genfscons: {0}".format(len(diff.removed_genfscons))) + for s in sorted(diff.removed_genfscons): + print(" - {0}".format(s)) + if diff.modified_genfscons and not args.stats: + print(" Modified Genfscons: {0}".format(len(diff.modified_genfscons))) + for entry in sorted(diff.modified_genfscons): + print(" * genfscon {0.fs} {0.path} {0.filetype} +[{1}] -[{2}];".format( + entry.rule, entry.added_context, entry.removed_context)) + + print() + except Exception as err: if args.debug: import traceback diff --git a/setools/diff/__init__.py b/setools/diff/__init__.py index 1043506..2f36614 100644 --- a/setools/diff/__init__.py +++ b/setools/diff/__init__.py @@ -19,6 +19,7 @@ from .bool import BooleansDifference from .commons import CommonDifference from .fsuse import FSUsesDifference +from .genfscon import GenfsconsDifference from .initsid import InitialSIDsDifference from .mls import CategoriesDifference, SensitivitiesDifference from .mlsrules import MLSRulesDifference @@ -37,6 +38,7 @@ class PolicyDifference(BooleansDifference, CategoriesDifference, CommonDifference, FSUsesDifference, + GenfsconsDifference, InitialSIDsDifference, MLSRulesDifference, ObjClassDifference, diff --git a/setools/diff/genfscon.py b/setools/diff/genfscon.py new file mode 100644 index 0000000..24f0a7d --- /dev/null +++ b/setools/diff/genfscon.py @@ -0,0 +1,92 @@ +# Copyright 2016, Tresys Technology, LLC +# +# This file is part of SETools. +# +# SETools 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. +# +# SETools 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 SETools. If not, see +# . +# +from collections import namedtuple + +from .context import ContextWrapper +from .descriptors import DiffResultDescriptor +from .difference import Difference, Wrapper + + +modified_genfs_record = namedtuple("modified_genfs", ["rule", + "added_context", + "removed_context"]) + + +class GenfsconsDifference(Difference): + + """Determine the difference in genfscon rules between two policies.""" + + added_genfscons = DiffResultDescriptor("diff_genfscons") + removed_genfscons = DiffResultDescriptor("diff_genfscons") + modified_genfscons = DiffResultDescriptor("diff_genfscons") + + def diff_genfscons(self): + """Generate the difference in genfscon rules between the policies.""" + + self.log.info( + "Generating genfscon differences from {0.left_policy} to {0.right_policy}". + format(self)) + + self.added_genfscons, self.removed_genfscons, matched = self._set_diff( + (GenfsconWrapper(fs) for fs in self.left_policy.genfscons()), + (GenfsconWrapper(fs) for fs in self.right_policy.genfscons())) + + self.modified_genfscons = [] + + for left_rule, right_rule in matched: + # Criteria for modified rules + # 1. change to context + if ContextWrapper(left_rule.context) != ContextWrapper(right_rule.context): + self.modified_genfscons.append(modified_genfs_record(left_rule, + right_rule.context, + left_rule.context)) + + # + # Internal functions + # + def _reset_diff(self): + """Reset diff results on policy changes.""" + self.log.debug("Resetting genfscon rule differences") + self.added_genfscons = None + self.removed_genfscons = None + self.modified_genfscons = None + + +class GenfsconWrapper(Wrapper): + + """Wrap genfscon rules to allow set operations.""" + + def __init__(self, rule): + self.origin = rule + self.fs = rule.fs + self.path = rule.path + self.filetype = rule.filetype + self.context = ContextWrapper(rule.context) + self.key = hash(rule) + + def __hash__(self): + return self.key + + def __lt__(self, other): + return self.key < other.key + + def __eq__(self, other): + return self.fs == other.fs and \ + self.path == other.path and \ + self.filetype == other.filetype diff --git a/tests/diff.py b/tests/diff.py index 03a7792..72058a0 100644 --- a/tests/diff.py +++ b/tests/diff.py @@ -1027,6 +1027,50 @@ class PolicyDifferenceTest(ValidateRule, unittest.TestCase): self.assertEqual("added_user:object_r:system:s1", added_context) self.assertEqual("removed_user:object_r:system:s0", removed_context) + # + # genfscon + # + def test_added_genfscons(self): + """Diff: added genfscons.""" + l = sorted(self.diff.added_genfscons) + self.assertEqual(2, len(l)) + + rule = l[0] + self.assertEqual("added_genfs", rule.fs) + self.assertEqual("/", rule.path) + self.assertEqual("added_user:object_r:system:s0", rule.context) + + rule = l[1] + self.assertEqual("change_path", rule.fs) + self.assertEqual("/new", rule.path) + self.assertEqual("system:object_r:system:s0", rule.context) + + def test_removed_genfscons(self): + """Diff: removed genfscons.""" + l = sorted(self.diff.removed_genfscons) + self.assertEqual(2, len(l)) + + rule = l[0] + self.assertEqual("change_path", rule.fs) + self.assertEqual("/old", rule.path) + self.assertEqual("system:object_r:system:s0", rule.context) + + rule = l[1] + self.assertEqual("removed_genfs", rule.fs) + self.assertEqual("/", rule.path) + self.assertEqual("system:object_r:system:s0", rule.context) + + def test_modified_genfscons(self): + """Diff: modified genfscons.""" + l = sorted(self.diff.modified_genfscons) + self.assertEqual(1, len(l)) + + rule, added_context, removed_context = l[0] + self.assertEqual("modified_genfs", rule.fs) + self.assertEqual("/", rule.path) + self.assertEqual("added_user:object_r:system:s0", added_context) + self.assertEqual("removed_user:object_r:system:s0", removed_context) + class PolicyDifferenceTestNoDiff(unittest.TestCase): @@ -1287,3 +1331,15 @@ class PolicyDifferenceTestNoDiff(unittest.TestCase): def test_modified_fs_uses(self): """NoDiff: no modified fs_uses.""" self.assertFalse(self.diff.modified_fs_uses) + + def test_added_genfscons(self): + """NoDiff: no added genfscons.""" + self.assertFalse(self.diff.added_genfscons) + + def test_removed_genfscons(self): + """NoDiff: no removed genfscons.""" + self.assertFalse(self.diff.removed_genfscons) + + def test_modified_genfscons(self): + """NoDiff: no modified genfscons.""" + self.assertFalse(self.diff.modified_genfscons) diff --git a/tests/diff_left.conf b/tests/diff_left.conf index 7f8c1ad..1003a1d 100644 --- a/tests/diff_left.conf +++ b/tests/diff_left.conf @@ -626,6 +626,9 @@ fs_use_trans modified_fsuse removed_user:object_r:system:s0; genfscon proc / system:object_r:system:s0 genfscon proc /sys system:object_r:system:s0 genfscon selinuxfs / system:object_r:system:s0 +genfscon removed_genfs / system:object_r:system:s0 +genfscon change_path /old system:object_r:system:s0 +genfscon modified_genfs / -s removed_user:object_r:system:s0 portcon tcp 80 system:object_r:system:s0 diff --git a/tests/diff_right.conf b/tests/diff_right.conf index 1ec7620..6387dd5 100644 --- a/tests/diff_right.conf +++ b/tests/diff_right.conf @@ -626,6 +626,9 @@ fs_use_trans modified_fsuse added_user:object_r:system:s1; genfscon proc / system:object_r:system:s0 genfscon proc /sys system:object_r:system:s0 genfscon selinuxfs / system:object_r:system:s0 +genfscon added_genfs / added_user:object_r:system:s0 +genfscon change_path /new system:object_r:system:s0 +genfscon modified_genfs / -s added_user:object_r:system:s0 portcon tcp 80 system:object_r:system:s0