Add logging.

Not comprehensive yet. Only planning to do setools pkg (not policyrep),
with the exception being the SELinuxPolicy class in policyrep.

Avoids performance-critical paths.  Use only info and debug so in normal
cases the user only sees messages if they ask for it (e.g. -v).
This commit is contained in:
Chris PeBenito 2015-03-19 08:07:23 -04:00
parent 97c80f22a5
commit de716ba6a5
10 changed files with 83 additions and 0 deletions

8
sedta
View File

@ -20,6 +20,7 @@
from __future__ import print_function
import sys
import argparse
import logging
import setools
@ -76,6 +77,8 @@ parser.add_argument("-s", "--source", help="Source type of the analysis.",
parser.add_argument("-t", "--target", help="Target type of the analysis.", default="")
parser.add_argument("--stats", action="store_true",
help="Display statistics at the end of the analysis.")
parser.add_argument("-v", "--verbose", action="store_true",
help="Print extra informational messages")
parser.add_argument("--debug", action="store_true", dest="debug", help="Enable debugging.")
alg = parser.add_argument_group("Analysis algorithm")
@ -97,6 +100,11 @@ if not args.target and (args.shortest_path or args.all_paths):
if args.target and not (args.shortest_path or args.all_paths):
parser.error("An algorithm must be specified to determine a path.")
if args.debug:
logging.basicConfig(level=logging.DEBUG)
elif args.verbose:
logging.basicConfig(level=logging.INFO)
try:
p = setools.SELinuxPolicy(args.policy)
g = setools.dta.DomainTransitionAnalysis(p, reverse=args.reverse, exclude=args.exclude)

8
seinfo
View File

@ -21,6 +21,7 @@ from __future__ import print_function
import setools
import argparse
import sys
import logging
parser = argparse.ArgumentParser(
description="SELinux policy information tool.")
@ -30,6 +31,8 @@ parser.add_argument("-x", "--expand", action="store_true",
help="Print additional information about the specified components.")
parser.add_argument("--flat", help="Print without item count nor indentation.",
dest="flat", default=False, action="store_true")
parser.add_argument("-v", "--verbose", action="store_true",
help="Print extra informational messages")
parser.add_argument("--debug", action="store_true", dest="debug", help="Enable debugging.")
queries = parser.add_argument_group("Component Queries")
@ -74,6 +77,11 @@ queries.add_argument("--all", help="Print all of the above.",
args = parser.parse_args()
if args.debug:
logging.basicConfig(level=logging.DEBUG)
elif args.verbose:
logging.basicConfig(level=logging.INFO)
try:
p = setools.SELinuxPolicy(args.policy)
components = []

View File

@ -21,6 +21,7 @@ from __future__ import print_function
import setools
import argparse
import sys
import logging
parser = argparse.ArgumentParser(
description="SELinux policy information flow analysis tool.",
@ -28,6 +29,8 @@ parser = argparse.ArgumentParser(
parser.add_argument("--version", action="version", version=setools.__version__)
parser.add_argument("--stats", action="store_true",
help="Display statistics at the end of the analysis.")
parser.add_argument("-v", "--verbose", action="store_true",
help="Print extra informational messages")
parser.add_argument("--debug", action="store_true", dest="debug", help="Enable debugging.")
settings = parser.add_argument_group("Analysis settings")
@ -65,6 +68,11 @@ if args.target and not (args.shortest_path or args.all_paths):
if args.limit_flows < 0:
parser.error("Limit on information flows cannot be negative.")
if args.debug:
logging.basicConfig(level=logging.DEBUG)
elif args.verbose:
logging.basicConfig(level=logging.INFO)
try:
p = setools.SELinuxPolicy(args.policy)
g = setools.infoflow.InfoFlowAnalysis(

View File

@ -21,12 +21,15 @@ from __future__ import print_function
import setools
import argparse
import sys
import logging
parser = argparse.ArgumentParser(
description="SELinux policy rule search tool.",
epilog="TE/MLS rule searches cannot be mixed with RBAC rule searches.")
parser.add_argument("--version", action="version", version=setools.__version__)
parser.add_argument("policy", help="Path to the SELinux policy to search.")
parser.add_argument("-v", "--verbose", action="store_true",
help="Print extra informational messages")
parser.add_argument("--debug", action="store_true", dest="debug", help="Enable debugging.")
rtypes = parser.add_argument_group("TE Rule Types")
@ -104,6 +107,11 @@ if not args.tertypes and not args.mlsrtypes and not args.rbacrtypes:
if (args.tertypes or args.mlsrtypes) and args.rbacrtypes:
parser.error("TE/MLS rule searches cannot be mixed with RBAC rule searches.")
if args.debug:
logging.basicConfig(level=logging.DEBUG)
elif args.verbose:
logging.basicConfig(level=logging.INFO)
try:
p = setools.SELinuxPolicy(args.policy)

View File

@ -17,6 +17,7 @@
# <http://www.gnu.org/licenses/>.
#
import itertools
import logging
from collections import defaultdict
import networkx as nx
@ -31,6 +32,8 @@ class DomainTransitionAnalysis(object):
Parameter:
policy The policy to analyze.
"""
self.log = logging.getLogger(self.__class__.__name__)
self.policy = policy
self.set_exclude(exclude)
self.set_reverse(reverse)
@ -339,6 +342,8 @@ class DomainTransitionAnalysis(object):
def _build_graph(self):
self.G.clear()
self.log.info("Building graph...")
# hash tables keyed on domain type
setexec = defaultdict(list)
setcurrent = defaultdict(list)
@ -509,6 +514,10 @@ class DomainTransitionAnalysis(object):
if self.rebuildgraph:
self._build_graph()
self.log.info("Building subgraph.")
self.log.debug("Excluding {0}".format(self.exclude))
self.log.debug("Reverse {0}".format(self.reverse))
# delete excluded domains from subgraph
nodes = [n for n in self.G.nodes() if n not in self.exclude]
# subgraph created this way to get copies of the edge

View File

@ -17,6 +17,7 @@
# <http://www.gnu.org/licenses/>.
#
import itertools
import logging
import networkx as nx
@ -38,6 +39,7 @@ class InfoFlowAnalysis(object):
exclude The types excluded from the information flow analysis.
(default is none)
"""
self.log = logging.getLogger(self.__class__.__name__)
self.policy = policy
@ -285,6 +287,8 @@ class InfoFlowAnalysis(object):
def _build_graph(self):
self.G.clear()
self.log.info("Building graph...")
self.perm_map.map_policy(self.policy)
for r in self.policy.terules():
@ -310,6 +314,10 @@ class InfoFlowAnalysis(object):
if self.rebuildgraph:
self._build_graph()
self.log.info("Building subgraph.")
self.log.debug("Excluding {0}".format(self.exclude))
self.log.debug("Min weight {0}".format(self.minweight))
# delete excluded types from subgraph
nodes = [n for n in self.G.nodes() if n not in self.exclude]
self.subG = self.G.subgraph(nodes)

View File

@ -16,6 +16,8 @@
# License along with SETools. If not, see
# <http://www.gnu.org/licenses/>.
#
import logging
from . import policyrep
@ -50,6 +52,8 @@ class PermissionMap(object):
Parameter:
permmapfile The path to the permission map to load.
"""
self.log = logging.getLogger(self.__class__.__name__)
self.load(permmapfile)
def load(self, permmapfile):
@ -57,6 +61,7 @@ class PermissionMap(object):
Parameter:
permmapfile The path to the permission map to load.
"""
self.log.info("Opening permission map \"{0}\"".format(permmapfile))
# state machine
# 1 = read number of classes
@ -236,6 +241,7 @@ class PermissionMap(object):
class_name = str(c)
if class_name not in self.permmap:
self.log.info("Adding unmapped class {0}".format(class_name))
self.permmap[class_name] = dict()
perms = c.perms
@ -247,6 +253,8 @@ class PermissionMap(object):
for perm_name in perms:
if perm_name not in self.permmap[class_name]:
self.log.info("Adding unmapped permission {0} in {1}".format(perm_name,
class_name))
self.permmap[class_name][perm_name] = {'direction': 'u',
'weight': 1,
'enabled': True}

View File

@ -20,6 +20,7 @@
# The idea is that this is module provides convenient
# abstractions and methods for accessing the policy
# structures.
import logging
from itertools import chain
from . import qpol
@ -72,6 +73,9 @@ class SELinuxPolicy(object):
policyfile Path to a policy to open.
"""
self.log = logging.getLogger(self.__class__.__name__)
self.log.info("Opening SELinux policy \"{0}\"".format(policyfile))
try:
self.policy = qpol.qpol_policy_t(policyfile, 0)
except SyntaxError as err:

View File

@ -16,6 +16,7 @@
# License along with SETools. If not, see
# <http://www.gnu.org/licenses/>.
#
import logging
import re
from .policyrep.rule import RuleUseError, RuleNotConditional
@ -63,6 +64,7 @@ class TERuleQuery(mixins.MatchPermission, rulequery.RuleQuery):
default_regex If true, regular expression matching will be
used on the default type.
"""
self.log = logging.getLogger(self.__class__.__name__)
self.policy = policy
@ -76,6 +78,17 @@ class TERuleQuery(mixins.MatchPermission, rulequery.RuleQuery):
def results(self):
"""Generator which yields all matching TE rules."""
self.log.info("Generating results.")
self.log.debug("Ruletypes: {0.ruletype}".format(self))
self.log.debug("Source: {0.source}, indirect: {0.source_indirect}, "
"regex: {0.source_regex}".format(self))
self.log.debug("Target: {0.target}, indirect: {0.target_indirect}, "
"regex: {0.target_regex}".format(self))
self.log.debug("Class: {0.tclass}, regex: {0.tclass_regex}".format(self))
self.log.debug("Perms: {0.perms}, eq: {0.perms_equal}".format(self))
self.log.debug("Default: {0.default}, regex: {0.default_regex}".format(self))
self.log.debug("Boolean: {0.boolean}, eq: {0.boolean_equal}, "
"regex: {0.boolean_regex}".format(self))
for r in self.policy.terules():
#

View File

@ -16,6 +16,7 @@
# License along with SETools. If not, see
# <http://www.gnu.org/licenses/>.
#
import logging
import re
from . import compquery
@ -62,6 +63,7 @@ class UserQuery(compquery.ComponentQuery):
range_proper If true, use proper superset/subset operations.
No effect if not using set operations.
"""
self.log = logging.getLogger(self.__class__.__name__)
self.policy = policy
self.set_name(name, regex=name_regex)
@ -72,6 +74,13 @@ class UserQuery(compquery.ComponentQuery):
def results(self):
"""Generator which yields all matching users."""
self.log.info("Generating results.")
self.log.debug("Name: {0.name}, regex: {0.name_regex}".format(self))
self.log.debug("Roles: {0.roles}, regex: {0.roles_regex}, eq: {0.roles_equal}".format(self))
self.log.debug("Level: {0.level}, dom: {0.level_dom}, domby: {0.level_domby}, "
"incomp: {0.level_incomp}".format(self))
self.log.debug("Range: {0.range_}, subset: {0.range_subset}, overlap: {0.range_overlap}, "
"superset: {0.range_superset}, proper: {0.range_proper}".format(self))
for u in self.policy.users():
if self.name and not self._match_regex(