-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 This patch makes audit2allow and audit2why the same executable rather then shipping a script for audit2why. This patch looks good to me. acked. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.15 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iEYEARECAAYFAlJpK6AACgkQrlYvE4MpobP0PgCgu0DHfFJAlFHAsaX2jwm3bp4s Fu4Anirsw1VbNIVplyA1e15U/QZRq/dh =f6/M -----END PGP SIGNATURE-----
>From 7005650148e4100d813e675d84ca7b1c451f8696 Mon Sep 17 00:00:00 2001 From: Dan Walsh <dwalsh@xxxxxxxxxx> Date: Wed, 9 Oct 2013 17:19:30 -0400 Subject: [PATCH 30/74] Handle audit2allow and audit2why with the same executable Remove audit2why directory and combine this into audit2allow directory --- policycoreutils/Makefile | 2 +- policycoreutils/audit2allow/Makefile | 7 +- policycoreutils/audit2allow/audit2allow | 8 +- policycoreutils/audit2allow/audit2why | 359 ++++++++++++++++++++++++++++++++ policycoreutils/audit2allow/audit2why.1 | 1 + policycoreutils/audit2why/Makefile | 18 -- policycoreutils/audit2why/audit2why | 2 - policycoreutils/audit2why/audit2why.1 | 1 - 8 files changed, 371 insertions(+), 27 deletions(-) create mode 100644 policycoreutils/audit2allow/audit2why create mode 100644 policycoreutils/audit2allow/audit2why.1 delete mode 100644 policycoreutils/audit2why/Makefile delete mode 100644 policycoreutils/audit2why/audit2why delete mode 100644 policycoreutils/audit2why/audit2why.1 diff --git a/policycoreutils/Makefile b/policycoreutils/Makefile index 3980799..83ebd45 100644 --- a/policycoreutils/Makefile +++ b/policycoreutils/Makefile @@ -1,4 +1,4 @@ -SUBDIRS = sepolicy setfiles semanage load_policy newrole run_init sandbox secon audit2allow audit2why sestatus semodule_package semodule semodule_link semodule_expand semodule_deps sepolgen-ifgen setsebool scripts po man gui +SUBDIRS = sepolicy setfiles semanage load_policy newrole run_init sandbox secon audit2allow sestatus semodule_package semodule semodule_link semodule_expand semodule_deps sepolgen-ifgen setsebool scripts po man gui INOTIFYH = $(shell ls /usr/include/sys/inotify.h 2>/dev/null) diff --git a/policycoreutils/audit2allow/Makefile b/policycoreutils/audit2allow/Makefile index 88635d4..fc290ea 100644 --- a/policycoreutils/audit2allow/Makefile +++ b/policycoreutils/audit2allow/Makefile @@ -5,14 +5,19 @@ LIBDIR ?= $(PREFIX)/lib MANDIR ?= $(PREFIX)/share/man LOCALEDIR ?= /usr/share/locale -all: ; +all: audit2why + +audit2why: + ln -sf audit2allow audit2why install: all -mkdir -p $(BINDIR) install -m 755 audit2allow $(BINDIR) + (cd $(BINDIR); ln -sf audit2allow audit2why) install -m 755 sepolgen-ifgen $(BINDIR) -mkdir -p $(MANDIR)/man1 install -m 644 audit2allow.1 $(MANDIR)/man1/ + install -m 644 audit2why.1 $(MANDIR)/man1/ clean: rm -f *~ diff --git a/policycoreutils/audit2allow/audit2allow b/policycoreutils/audit2allow/audit2allow index 49a342d..9f5185d 100644 --- a/policycoreutils/audit2allow/audit2allow +++ b/policycoreutils/audit2allow/audit2allow @@ -1,7 +1,8 @@ #! /usr/bin/python -Es # Authors: Karl MacMillan <kmacmillan@xxxxxxxxxxxxxxxxx> +# Authors: Dan Walsh <dwalsh@xxxxxxxxxx> # -# Copyright (C) 2006-2007 Red Hat +# Copyright (C) 2006-2013 Red Hat # see file 'COPYING' for use and warranty information # # This program is free software; you can redistribute it and/or @@ -18,7 +19,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # -import sys +import sys, os import sepolgen.audit as audit import sepolgen.policygen as policygen @@ -82,8 +83,7 @@ class AuditToPolicy: parser.add_option("--interface-info", dest="interface_info", help="file name of interface information") parser.add_option("--debug", dest="debug", action="store_true", default=False, help="leave generated modules for -M") - - parser.add_option("-w", "--why", dest="audit2why", action="store_true", default=False, + parser.add_option("-w", "--why", dest="audit2why", action="store_true", default=(os.path.basename(sys.argv[0])=="audit2why"), help="Translates SELinux audit messages into a description of why the access was denied") options, args = parser.parse_args() diff --git a/policycoreutils/audit2allow/audit2why b/policycoreutils/audit2allow/audit2why new file mode 100644 index 0000000..9f5185d --- /dev/null +++ b/policycoreutils/audit2allow/audit2why @@ -0,0 +1,359 @@ +#! /usr/bin/python -Es +# Authors: Karl MacMillan <kmacmillan@xxxxxxxxxxxxxxxxx> +# Authors: Dan Walsh <dwalsh@xxxxxxxxxx> +# +# Copyright (C) 2006-2013 Red Hat +# see file 'COPYING' for use and warranty information +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; version 2 only +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +import sys, os + +import sepolgen.audit as audit +import sepolgen.policygen as policygen +import sepolgen.interfaces as interfaces +import sepolgen.output as output +import sepolgen.objectmodel as objectmodel +import sepolgen.defaults as defaults +import sepolgen.module as module +from sepolgen.sepolgeni18n import _ +import selinux.audit2why as audit2why +import locale +locale.setlocale(locale.LC_ALL, '') + +class AuditToPolicy: + VERSION = "%prog .1" + SYSLOG = "/var/log/messages" + + def __init__(self): + self.__options = None + self.__parser = None + self.__avs = None + + def __parse_options(self): + from optparse import OptionParser + + parser = OptionParser(version=self.VERSION) + parser.add_option("-b", "--boot", action="store_true", dest="boot", default=False, + help="audit messages since last boot conflicts with -i") + parser.add_option("-a", "--all", action="store_true", dest="audit", default=False, + help="read input from audit log - conflicts with -i") + parser.add_option("-p", "--policy", dest="policy", default=None, help="Policy file to use for analysis") + parser.add_option("-d", "--dmesg", action="store_true", dest="dmesg", default=False, + help="read input from dmesg - conflicts with --all and --input") + parser.add_option("-i", "--input", dest="input", + help="read input from <input> - conflicts with -a") + parser.add_option("-l", "--lastreload", action="store_true", dest="lastreload", default=False, + help="read input only after the last reload") + parser.add_option("-r", "--requires", action="store_true", dest="requires", default=False, + help="generate require statements for rules") + parser.add_option("-m", "--module", dest="module", + help="set the module name - implies --requires") + parser.add_option("-M", "--module-package", dest="module_package", + help="generate a module package - conflicts with -o and -m") + parser.add_option("-o", "--output", dest="output", + help="append output to <filename>, conflicts with -M") + parser.add_option("-D", "--dontaudit", action="store_true", + dest="dontaudit", default=False, + help="generate policy with dontaudit rules") + parser.add_option("-R", "--reference", action="store_true", dest="refpolicy", + default=True, help="generate refpolicy style output") + + parser.add_option("-N", "--noreference", action="store_false", dest="refpolicy", + default=False, help="do not generate refpolicy style output") + parser.add_option("-v", "--verbose", action="store_true", dest="verbose", + default=False, help="explain generated output") + parser.add_option("-e", "--explain", action="store_true", dest="explain_long", + default=False, help="fully explain generated output") + parser.add_option("-t", "--type", help="only process messages with a type that matches this regex", + dest="type") + parser.add_option("--perm-map", dest="perm_map", help="file name of perm map") + parser.add_option("--interface-info", dest="interface_info", help="file name of interface information") + parser.add_option("--debug", dest="debug", action="store_true", default=False, + help="leave generated modules for -M") + parser.add_option("-w", "--why", dest="audit2why", action="store_true", default=(os.path.basename(sys.argv[0])=="audit2why"), + help="Translates SELinux audit messages into a description of why the access was denied") + + options, args = parser.parse_args() + + # Make -d, -a, and -i conflict + if options.audit is True or options.boot: + if options.input is not None: + sys.stderr.write("error: --all/--boot conflicts with --input\n") + if options.dmesg is True: + sys.stderr.write("error: --all/--boot conflicts with --dmesg\n") + if options.input is not None and options.dmesg is True: + sys.stderr.write("error: --input conflicts with --dmesg\n") + + # Turn on requires generation if a module name is given. Also verify + # the module name. + if options.module: + name = options.module + else: + name = options.module_package + if name: + options.requires = True + if not module.is_valid_name(name): + sys.stderr.write('error: module names must begin with a letter, optionally followed by letters, numbers, "-", "_", "."\n') + sys.exit(2) + + # Make -M and -o conflict + if options.module_package: + if options.output: + sys.stderr.write("error: --module-package conflicts with --output\n") + sys.exit(2) + if options.module: + sys.stderr.write("error: --module-package conflicts with --module\n") + sys.exit(2) + + self.__options = options + + def __read_input(self): + parser = audit.AuditParser(last_load_only=self.__options.lastreload) + + filename = None + messages = None + f = None + + # Figure out what input we want + if self.__options.input is not None: + filename = self.__options.input + elif self.__options.dmesg: + messages = audit.get_dmesg_msgs() + elif self.__options.audit: + try: + messages = audit.get_audit_msgs() + except OSError, e: + sys.stderr.write('could not run ausearch - "%s"\n' % str(e)) + sys.exit(1) + elif self.__options.boot: + try: + messages = audit.get_audit_boot_msgs() + except OSError, e: + sys.stderr.write('could not run ausearch - "%s"\n' % str(e)) + sys.exit(1) + else: + # This is the default if no input is specified + f = sys.stdin + + # Get the input + if filename is not None: + try: + f = open(filename) + except IOError, e: + sys.stderr.write('could not open file %s - "%s"\n' % (filename, str(e))) + sys.exit(1) + + if f is not None: + parser.parse_file(f) + f.close() + + if messages is not None: + parser.parse_string(messages) + + self.__parser = parser + + def __process_input(self): + if self.__options.type: + avcfilter = audit.AVCTypeFilter(self.__options.type) + self.__avs = self.__parser.to_access(avcfilter) + csfilter = audit.ComputeSidTypeFilter(self.__options.type) + self.__role_types = self.__parser.to_role(csfilter) + else: + self.__avs = self.__parser.to_access() + self.__role_types = self.__parser.to_role() + + def __load_interface_info(self): + # Load interface info file + if self.__options.interface_info: + fn = self.__options.interface_info + else: + fn = defaults.interface_info() + try: + fd = open(fn) + except: + sys.stderr.write("could not open interface info [%s]\n" % fn) + sys.exit(1) + + ifs = interfaces.InterfaceSet() + ifs.from_file(fd) + fd.close() + + # Also load perm maps + if self.__options.perm_map: + fn = self.__options.perm_map + else: + fn = defaults.perm_map() + try: + fd = open(fn) + except: + sys.stderr.write("could not open perm map [%s]\n" % fn) + sys.exit(1) + + perm_maps = objectmodel.PermMappings() + perm_maps.from_file(fd) + + return (ifs, perm_maps) + + def __output_modulepackage(self, writer, generator): + generator.set_module_name(self.__options.module_package) + filename = self.__options.module_package + ".te" + packagename = self.__options.module_package + ".pp" + + try: + fd = open(filename, "w") + except IOError, e: + sys.stderr.write("could not write output file: %s\n" % str(e)) + sys.exit(1) + + writer.write(generator.get_module(), fd) + fd.close() + + mc = module.ModuleCompiler() + + try: + mc.create_module_package(filename, self.__options.refpolicy) + except RuntimeError, e: + print e + sys.exit(1) + + sys.stdout.write(_("******************** IMPORTANT ***********************\n")) + sys.stdout.write((_("To make this policy package active, execute:" +\ + "\n\nsemodule -i %s\n\n") % packagename)) + + def __output_audit2why(self): + import selinux + import seobject + for i in self.__parser.avc_msgs: + rc = i.type + data = i.data + if rc >= 0: + print "%s\n\tWas caused by:" % i.message + if rc == audit2why.ALLOW: + print "\t\tUnknown - would be allowed by active policy\n", + print "\t\tPossible mismatch between this policy and the one under which the audit message was generated.\n" + print "\t\tPossible mismatch between current in-memory boolean settings vs. permanent ones.\n" + continue + if rc == audit2why.DONTAUDIT: + print "\t\tUnknown - should be dontaudit'd by active policy\n", + print "\t\tPossible mismatch between this policy and the one under which the audit message was generated.\n" + print "\t\tPossible mismatch between current in-memory boolean settings vs. permanent ones.\n" + continue + if rc == audit2why.BOOLEAN: + if len(data) > 1: + print "\tOne of the following booleans was set incorrectly." + for b in data: + print "\tDescription:\n\t%s\n" % seobject.boolean_desc(b[0]) + print "\tAllow access by executing:\n\t# setsebool -P %s %d" % (b[0], b[1]) + else: + print "\tThe boolean %s was set incorrectly. " % (data[0][0]) + print "\tDescription:\n\t%s\n" % seobject.boolean_desc(data[0][0]) + print "\tAllow access by executing:\n\t# setsebool -P %s %d" % (data[0][0], data[0][1]) + continue + + if rc == audit2why.TERULE: + print "\t\tMissing type enforcement (TE) allow rule.\n" + print "\t\tYou can use audit2allow to generate a loadable module to allow this access.\n" + continue + + if rc == audit2why.CONSTRAINT: + print #!!!! This avc is a constraint violation. You would need to modify the attributes of either the source or target types to allow this access.\n" + print "#Constraint rule: \n\t" + data[0] + for reason in data[1:]: + print "#\tPossible cause is the source %s and target %s are different.\n\b" % reason + + if rc == audit2why.RBAC: + print "\t\tMissing role allow rule.\n" + print "\t\tAdd an allow rule for the role pair.\n" + continue + + audit2why.finish() + return + + def __output(self): + + if self.__options.audit2why: + try: + return self.__output_audit2why() + except RuntimeError, e: + print e + sys.exit(1) + + g = policygen.PolicyGenerator() + + g.set_gen_dontaudit(self.__options.dontaudit) + + if self.__options.module: + g.set_module_name(self.__options.module) + + # Interface generation + if self.__options.refpolicy: + ifs, perm_maps = self.__load_interface_info() + g.set_gen_refpol(ifs, perm_maps) + + # Explanation + if self.__options.verbose: + g.set_gen_explain(policygen.SHORT_EXPLANATION) + if self.__options.explain_long: + g.set_gen_explain(policygen.LONG_EXPLANATION) + + # Requires + if self.__options.requires: + g.set_gen_requires(True) + + # Generate the policy + g.add_access(self.__avs) + g.add_role_types(self.__role_types) + + # Output + writer = output.ModuleWriter() + + # Module package + if self.__options.module_package: + self.__output_modulepackage(writer, g) + else: + # File or stdout + if self.__options.module: + g.set_module_name(self.__options.module) + + if self.__options.output: + fd = open(self.__options.output, "a") + else: + fd = sys.stdout + writer.write(g.get_module(), fd) + + def main(self): + try: + self.__parse_options() + if self.__options.policy: + audit2why.init(self.__options.policy) + else: + audit2why.init() + + self.__read_input() + self.__process_input() + self.__output() + except KeyboardInterrupt: + sys.exit(0) + except ValueError, e: + print e + sys.exit(1) + except IOError, e: + print e + sys.exit(1) + +if __name__ == "__main__": + app = AuditToPolicy() + app.main() diff --git a/policycoreutils/audit2allow/audit2why.1 b/policycoreutils/audit2allow/audit2why.1 new file mode 100644 index 0000000..a9e8893 --- /dev/null +++ b/policycoreutils/audit2allow/audit2why.1 @@ -0,0 +1 @@ +.so man1/audit2allow.1 diff --git a/policycoreutils/audit2why/Makefile b/policycoreutils/audit2why/Makefile deleted file mode 100644 index 63eb8b3..0000000 --- a/policycoreutils/audit2why/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -# Installation directories. -PREFIX ?= $(DESTDIR)/usr -BINDIR ?= $(PREFIX)/bin -MANDIR ?= $(PREFIX)/share/man - -TARGETS=audit2why - -all: $(TARGETS) - -install: all - -mkdir -p $(BINDIR) - install -m 755 $(TARGETS) $(BINDIR) - -mkdir -p $(MANDIR)/man1 - install -m 644 audit2why.1 $(MANDIR)/man1/ - -clean: - -relabel: diff --git a/policycoreutils/audit2why/audit2why b/policycoreutils/audit2why/audit2why deleted file mode 100644 index 21a72aa..0000000 --- a/policycoreutils/audit2why/audit2why +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -/usr/bin/audit2allow -w $* diff --git a/policycoreutils/audit2why/audit2why.1 b/policycoreutils/audit2why/audit2why.1 deleted file mode 100644 index a9e8893..0000000 --- a/policycoreutils/audit2why/audit2why.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/audit2allow.1 -- 1.8.3.1