PolicyDifference: implement genfscon diff

Closes #41
This commit is contained in:
Chris PeBenito 2016-01-11 14:43:11 -05:00
parent ee1c0b3328
commit afeb3561d2
6 changed files with 178 additions and 0 deletions

22
sediff
View File

@ -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

View File

@ -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,

92
setools/diff/genfscon.py Normal file
View File

@ -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
# <http://www.gnu.org/licenses/>.
#
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

View File

@ -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)

View File

@ -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

View File

@ -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