Copyright © 2004 The MITRE Corporation.
Permission to copy without fee all or part of this material is granted provided that the copies are not made or distributed for direct commercial advantage, this copyright notice and the title of the publication and its date appear, and notice in given that copying is by permission of The MITRE Corporation.
In January of 2001, the National Security Agency released a prototype version of a security-enhanced Linux system. Mandatory Access Control (MAC) security mechanisms were implemented, providing flexible support for a wide range of security policies. Both type enforcement and role-based access control components were incorporated into the access controls.
This document describes how to use MITRE's SELinux policy generation
tools, collectively called polgen, which provide a systematic way
to generate policy for programs on an SELinux system. Specifically,
polgen attempts to generate policy for a program based on
patterns in the program's behavior. This process is predictable and
repeatable, but interactive. The user, presented with a suggested policy
description, can modify that description before actual policy is
produced. Also, polgen supports optional policy analysis to
ensure that the newly generated policy does not adversely affect
existing (enforced) security goals.
The basic steps of polgen usage are:
.te files.
This manual assumes some knowledge of the SELinux system. In particular, we assume the reader is familiar with the following SELinux concepts: basic SELinux enforcement mechanism, policy file format, security contexts, and class-permission pairs. If you are unfamiliar with the basics of these concepts, please refer to "Configuring the SELinux Policy", which is included in the SELinux distribution. The section titled "Flask Concepts" is particularly important.
This manual begins with a quick overview (without explanation or
discussion) of polgen usage in Quick Start. We present
more detail about each of the components in subsequent sections. In
Type Generation, we discuss the use of typegen to set up
initial types for candidate programs (this is very helpful for
deciphering later polgen output). In Capturing Program Behavior, we describe the use of an enhanced version of strace
and associated filtering scripts to capture system call-level program
behavior and SELinux information. In Recognizing Patterns, we
provide an overview of our behavior analysis approach and cover the use
of the spar pattern recognizer. In Generating Policy, we
cover the use of the spec2pol program. In Batch-Processing Script, we provide the user with a modifiable script that will run all
post-strace polgen components. Finally, we provide a
guide to the worked example included in this distribution in the
Complete Example section.
In all sections of this manual, we will use pol_source_directory
to denote the location of the SELinux policy source. Under FC2, this
will be /etc/security/selinux/src/policy. Under FC3, this will
either be /etc/selinux/targeted/src/policy (by default) or
/etc/selinux/strict/src/policy (if you have switched to the
optional strict policy).
We start this section with a short list of commands run in the most
typical use of polgen. In the remainder of this Quick Start
section, we provide a small amount of detail on what the various
commands mean. Much more information is available in the subsequent
sections of this document.
Substitute the program you wish to analyze for program_name, and
the directory into which you want to install the software for
$HOME/polgen.
$ ./configure --prefix=$HOME/polgen
$ make
$ make install
$ export PATH=$HOME/polgen/bin:$PATH
$ cd workdir
$ cp $HOME/polgen/share/polgen/typegen.conf .
$ emacs typegen.conf
$ typegen
$ a=pol_source_directory
$ cp program_name.te $a/domains/program
$ cp program_name.fc $a/file_contexts/program
$ pushd $a
$ make reload
$ /usr/sbin/setfiles file_contexts/file_contexts workdir
$ pushd
$ strace -fX -o trace_path program_name command_line_args
$ trackall -o track_data_dir trace_path
$ spar -n program_name -d track_data_dir -o results_data_dir
$ spec2pol result_data_dir/program_name_policy_spec.py
These tools are packaged according to GNU standards. For complete
information, see the INSTALL file included with this
distribution. However, the distribution can be easily compiled and
installed in the following way:
./configure. This software will be
installed into /usr by default. If you would like to install
the software in location $HOME/polgen, run the command
./configure --prefix=$HOME/polgen. Be sure to add
$HOME/polgen/bin to your path.
make to compile the package.
make install to install the programs, data files, and
documentation.
The generation process can be performed entirely on an SELinux machine,
or it can be split between an SELinux machine and another machines. The
type generation, strace, and strace filtering components
must be run on an SELinux system. Pattern recognition and policy
generation can be performed elsewhere if desired; use the
--with-strace=no option when installing polgen on the
secondary system.
Once installation is complete, there are four distinct phases when
generating policy with polgen.
The typegen script generates a basic set of .te and
.fc files for a given set of executables, directories, and
files. typegen determines which new types to incorporate based on
its configuration file, which can optionally be specified with the
-i command line flag. If no command line options are specified,
typegen will look for the file typegen.conf in the current
working directory.
Details of the configuration file can be found in the Type Generation section and a sample configuration is included in this
distribution under prefix/share/polgen. The following
commands, given an appropriate configuration file, will generate and
install new types and relabel the relevant portions of the file
system. We assume for this example that you chose program for
your program name, and that the candidate program and all of its
relevant files are in the directory workdir.
$ typegen
$ a=pol_source_directory
$ cp program_name.te $a/domains/program
$ cp program_name.fc $a/file_contexts/program
$ pushd $a
$ make reload
$ /usr/sbin/setfiles file_contexts/file_contexts workdir
On the target SELinux system, run the strace program
(located in the bin directory) on the target program and any
related programs:
$ strace -fX -o trace_path program_name command_line_args
$ trackall -o track_data_dir trace_path
While the program is running, exercise it in as many different ways as
possible. The trackall program will run filters on the strace
output, and produce digested trace files containing system call
information useful for pattern recognition. With the optional
-o, trackall will store its output in the given
directory. The naming convention for these files is they all begin with
program_name.tracked, and they can be moved to the system
or location where you will generate policy.
The program spar, the Security-enhanced linux PAttern
Recognizer, searches processed strace files for particular
behavior patterns and presents them to the user through a collection
of web pages.
The eventual use-case for this generation software is for large patterns
to be recognized and communicated to the user, e.g. "This program is a
web server", based on a particular collection of modular sub-patterns
found in the program's behavior (e.g., "This program is a network daemon
listening on port 80 that uses configuration files, log files, and
interacts with user files while running."). Currently, spar
recognizes some higher-level security patterns and some modular pattern
"building blocks". The complete list of patterns is listed in the full
section Recognizing Patterns.
The spar program provides you with the freedom to locate your
trace results (spar input) and results (spar output) in
directories of your choosing. In the commands that follow, we refer to
these two directories as track_data_dir, and
results_data_dir, respectively.
If you ran trackall with the -o option,
track_data_dir will be the output directory you specified in the
previous step. Run spar as follows:
$ spar -n program_name -d track_data_dir -o results_data_dir
You may then examine the patterns and policy suggested in
PolicyHelp.html, in results_data_dir.
.te filesYou must carefully study and edit
result_data_dir/program_name_policy_spec.py. Once
you are satisfied with it, use it to generate a .te file with
the following command.
$ spec2pol results_data_dir/program_name_policy_spec.py
The typegen script generates a basic set of .te and
.fc files for a given set of executables, directories, and
files. typegen determines which new types to incorporate based on
its configuration file, which can optionally be specified with the
-i command line flag. If no command line options are specified,
typegen will look for the file typegen.conf in the current
working directory.
typegen currently supports the following optional command line
flags:
-i <file> option specifies a configuration file as
input.
-v option prints version information.
-h option prints a usage message.
The configuration file, typegen.conf, requires four types of
statement and supports an additional three.
name program_name
This is a required statement. The name keyword allows the user to
specify a program-wide abstraction that will tie all types related to
this program together. All types that typegen creates and assigns
will be prepended with program_name.
role desiredrole_r types desiredtype_1 desiredtype_2 ... desiredtype_n
At least one role statement is required, but typegen
supports multiple statements. This statement specifies a role and set of
types allowed to run the program. (To determine your own role, run
'getcon'.
tedir output_directory_name
This is a required statement. The tedir keyword specifies the
path to the output directory for the .te file generated by
typegen.
fcdir output_directory_name
This is a required statement. The fcdir keyword specifies the
path to the output directory for the .fc file generated by
typegen.
exec process_name path_to_executable
This is an optional statement, and you may have as many exec
declarations as you would like. This statement assigns a user-specified
name to an executable for type generation purposes. For example, given
the commands specified here the executable file would be given
the type program_name_process_name_exec_t. The path must be fully
specified.
dir dir_name path_to_dir
This is an optional statement, and you may have as many dir
declarations as you would like. This statement assigns a user-specified
name to a directory or set of directories for type declaration
purposes. The path listed may be a regular expression. The name will be
used in the creation of types for the directories.
file file_name path_to_file
This is an optional statement, and you may have as many file
declarations as you would like. This statement assigns a user-specified
name to a file for type declaration purposes. The name will be used in
the creation of types for the file.
typegen OutputInto the directories specified in the configuration file,
typegen will produce two files: program_name.te
and program_name.fc where program_name is the name
specified in the configuration file.
The .te file will contain the following policy declarations:
type declarations for any processes specified in the
configuration file. typegen will produce one domain type
declaration for the process itself, and one type declaration for the
on-disk executable file.
type declarations for all files and directories specified
in the configuration file.
role declaration associating the desired role with new
types for each process declared in the configuration file.
allow declaration lines permitting the relevant process
transitions.
type_transition statements for each of the processes
specified in the configuration file.
The .fc file will contain one line for each assignment of types
to the files, directories, and executables declared in the configuration
file.
typegen OutputOnce typegen has produced .te and .fc files, they
must be incorporated into the running policy before appropriate traces
can be captured. The following steps will accomplish this:
.te file into the
pol_source_directory/domains/program directory.
.fc file into the
pol_source_directory/file_contexts/program directory.
make reload.
setfiles program on all directories you wish to
relabel. For directory path_to_foo, run the following command:
$ /usr/sbin/setfiles pol_source_directory/file_contexts/file_contexts path_to_foo
Your processes, directories, and files should now all be labeled with
new types. (You can check this by using the -Z option to
ls.) These new types will be used for the generation of
program-specific policy by the rest of the polgen tools.
The program behavior should be captured on an SELinux machine. All
examples run so far have been on a system in permissive mode; no special
policy has been written to allow strace to function properly in
enforcing mode (though this is planned for future releases of
polgen).
When you run the target program under strace, exercise it as
fully as possible. As with all dynamic analysis approaches, the
completeness of the traces will dictate the robustness of the policy.
$ strace -fX -o program program
$ trackall -o output_directory program
These commands will produce trace files containing system call
information useful for pattern recognition. When trackall is
called with the -o option, the script will place output files
in output_directory. The naming convention for these files is
program.tracked, and it can be moved to the system or
location where you will generate policy.
trackall WorksThe trackall program converts strace output into a format
that is easy to analyze, and then invokes the trackfd program.
The trackfd program performs the data reduction for the
spar program. This script can also be useful outside of the
policy generation context, to make sense of trace files and offer
insight into a program's behavior.
An essential part of the data reduction is the summarization of the
life cycle of a file descriptor. For each file descriptor created by
a program, the trackfd program creates a data structure. The
data structure is updated whenever a system call is found that applies
to the file descriptor. Finally, when a file descriptor is closed, a
summary of the activity associated with the file descriptor is written
to the output.
These tools were designed to help SELinux administrators generate modular, predictable policy for individual programs. Our approach is based upon the identification of interaction patterns in program behavior, eventually at multiple abstraction levels. As patterns are recognized in program behavior (and perhaps modified by the user), policy targeted to those specific interactions can be generated. This approach will produce policy that is specifically tied to an individual program, and can support least-privilege in a predictable and repeatable way.
Currently, our tools look for low-level process interaction patterns in
the behavior of the target program (such as the use of temporary files).
For each of these individual patterns, our tools suggest policy
descriptions to the end user, who can then modify the policy
descriptions before actual .te files are generated.
The eventual use-case for this generation software is for large patterns to be recognized and communicated to the user, (e.g., "This program is a web server") based on a particular collection of modular sub-patterns found in the program's behavior (e.g., "This program is a network daemon listening on port 80 that uses configuration files, log files, and interacts with user files while running.").
The program spar, the Security-enhanced linux PAttern
Recognizer, searches processed trace files for particular behavior
patterns and presents them to a user through a collection of web pages
and a policy spec file. The user can then modify the spec file and use
spec2pol to generate SELinux policy files for the candidate
programs.
sparCurrently, spar recognizes some higher-level security patterns
and some modular pattern "building blocks". The complete list of
patterns recognized in program behavior follows. In some cases, there
are multiple recognizer modules for each pattern. Future versions of
these tools will recognize more patterns, and may also include more
sophisticated recognizers for existing patterns.
write() system calls in the /tmp directory.
open()
system call on a file containing the string .so somewhere in
the file name.
var/log.
etc or if files are
accessed beginning with a . (anywhere in the file system).
libselinux initialization, which happens often as many programs
are now linked against libselinux. There are two levels of
policy suggestion for this pattern, one of which is currently
implemented. If the program is linked against libselinux and
later invokes a call that needs access to selinuxfs or an
/etc/selinux/$SELINUXTYPE policy file, we suggest rules
allowing the program to make the access. We recognize this linking if
a program shows attempts to read from /proc/mounts or
/etc/selinux/config, with subsequent accesses to nodes in
selinuxfs or /etc/selinux. In future versions, if the
program never actually invokes a call needing such access, we will
suggest policy incorporating a dontaudit statement.
/proc/filesystems and
/proc/self/attr/current. The policy recommended is to allow the
application type to read from the appropriate types for these files.
Future versions of spar will also recognize near-matches for
patterns, and allow the user to confirm, deny, and/or modify policy for
those near-patterns.
sparThe spar program provides you with the freedom to locate your
tracking results (spar input), and results (spar output)
in directories of your choosing. In what follows, we refer to these
two directories as track_data_dir, and results_data_dir,
respectively.
If you ran trackall with the -o option,
track_data_dir will be the output directory you specified in
the previous step.
The spar program is run from a Unix shell. The command line
arguments for running spar are as follows.
-h: Help
-n: Specify name for program - default is the name of the
directory where tracked data is located
-d: Specify tracked data directory - default is directory
in which spar is run
-o: Specify output directory - default is to create a
subdirectory named results inside the directory where
spar is run.
This command is used to analyze data from the track_data_dir
directory. The output is placed in the results_data_dir
directory and the analyzed program name is myprog.
$ spar -n myprog -d track_data_dir -o results_data_dir
When you run spar, you will see running commentary as
spar reads tracked files generated from strace,
identifies pattern use, and writes out results in XML, HTML and Python
formats.
spar OutputHuman intervention in the spar output files is almost certain to
be needed before generating final policy. However, spar helps
focus the human interaction by highlighting decision points and likely
conflicts. It presents both complete sets of patterns to the user, and
also identifies incomplete patterns, and incomplete groups of patterns
(e.g., a program might be classified as a web server if only it used
configuration files). There are three types of reports in spar's
output directory, as specified on the command line.
spar's findings and allow for easier editing
for the third type of file, a python script. They offer information
grouped in five different files:
spar are listed, along with the name of the tracked file from
which they came. Next to the process name/PID, the security context of
that process is listed.
spar are listed. At the top of the page, a list of all patterns
for which spar is looking is shown, with actual found instances
hyperlinked. The rest of the page goes through the recognized patterns
by type. For each one, a picture and all context/file descriptor
information is shown.
spar lists all
policy changes that require action to be taken by the user. If the
tracked files didn't provide a security context, for example, this will
be highlighted on the Manual Action Required page. New type assignments
and resources for which there are multiple type generation constraints
(for example, if a program tries to write to an already-existing file)
are also shown here.
spar are
listed, along with their security contexts.
spar presents the user with
all processes and resources found, grouped according to security
context.
.te file. For more information, see the Generating Policy section below.
Most users will use spar in "batch" mode as described in these
instructions thus far. However, if you are interested in examining
spar capabilities in more detail, doing interactive explorations
of a program's structure, or actually extending spar itself, this
section provides information on the recognition process.
class RecogPipeline (SpecObj):
pattern = Pipeline
detection = "correct"
__pat1 = ("r1 is_an element from nodes_in"
+ " [c.range for c in obj.out_edges"
+ " if len(c.range.in_edges) == 1"
+ " and c.action == 'write']")
__pat2 = ("middle is_an element from nodes_in"
+ " [c.range for c in r1.out_edges"
+ " if c.range != obj"
+ " and c.action == 'read'"
+ " and c.domain not in obj.receiving_from]")
__pat3 = ("r2 is_an element from nodes_in"
+ " [c.range for c in middle.out_edges"
+ " if len(c.range.in_edges) == 1"
+ " and c.action == 'write']")
__pat4 = ("end is_a set from nodes_in"
+ " [c.range for c in r2.out_edges"
+ " if c.range not in obj.receiving_from"
+ " and c.range != obj"
+ " and c.range != middle"
+ " and c.action == 'read'"
+ " and c.range not in middle.receiving_from]")
collections = [
Recog(__pat1,
[Recog(_pat2,
[Recog(__pat3,
[Recog(__pat4)])])])]
focus_name = "begin"
Recognizers are written in a semi-declarative fashion. What appears
above is a Python class which defines a recognizer for Pipeline. The
class has several attributes including "pattern" (i.e., the name of
the pattern that is recognized), "collections" (descriptions of how to
locate the constituent parts of the pattern), and "focus_name" (the
name of the resource at the top of the chain). spar will
compile this semi-declarative description into procedural Python code
and place it in the current directory. This procedural code walks
through all the resources identifying each one as the focus_name
participant and then follows information and execution flow to other
resources looking for matches to the constraints embedded in the
collections. For example,
Recog("r1 is_an element from nodes_in [c.range for c in obj.out_edges]")
states that r1 participants are nodes in the out_edges of obj - a local
variable bound to the begin resource at top level. The format for Recog
arguments is as follows. The first argument is a string of the form
"participant-name is_an element from nodes_in arbitrary Python code
returning a list". The second optional argument is a list of
additional recognition descriptions using the obj and any above
participant names as local variables.
Running the procedural code stores solution trees in internal memory. A global class in the util module called PRGM holds all of the instances extracted. Each instance is a tree with root set to the "focus_name" participant and subtrees generated for collections of other participants. This information is stored as a dictionary with keys set to the names of the recognizers. Hence
Util.PRGM.pattern_instances['RecogPipeline'] will return a collection of trees.
Items on these trees can then be explored in an interactive session using the Python interpreter.
After spar is finished, there will be three types of file in the
spar_output directory. The HTML files are meant to aid human
understanding, and provide a hyper-linked way to browse the suggested
policy (as described above in Recognizing Patterns). The file
(program)_policy_spec.py, when run via spec2pol, will
produce .te (and in the future, .fc) policy files.
This file contains both comments (lines beginning with '#') and
uncommented lines that are used to generate a .te file. The
policy author should make appropriate modifications to this file by
deleting or replacing uncommented lines prior to running
spec2pol. Each uncommented line can be interpreted by
Python. The syntax for all lines is <function-name>(<comma
delimited security contexts>). All arguments are strings. In Python,
strings are notated with matching single, double, or triple quotes.
Function names and argument meanings include the following:
Declare(new-type, type)
AllowR(process-context, resource-context, action):
This function produces an allow statement granting
action permissions to process-context against
resource-context.
CanExecR([type-do-the-execs, type-exec'ds, ....]):
In addition, there is a function for each pattern type. Thus the
policy_spec file will contain lines of the form
<pattern-name>R(contexts,...). For each pattern
instance, the file will contain a commented version of the pattern
instance (using previously-existing types), and an uncommented version
of the pattern instance (using the new types polgen
suggests). There are a variable number of contexts per pattern
depending upon the pattern definition. We do not anticipate that
authors will be adding pattern instance lines to this file. However,
authors will often wish to modify contexts or delete entire
instances.
The enclosed script runs the three programs that analyze strace
output. Before use, it should be adjusted to fit your needs. Note that
if you use this script, you will get .te files directly, without
any chance to modify the program_policy_spec.py file.
#! /bin/sh
# Run polgen post strace programs.
# Change the following settings to your tastes.
# Set this to polgen's bin directory if it is not on your path.
bindir=
# Derive the name of the system being analyzed
# from the current directory name.
name=$(basename $(pwd))
# Directory containing the strace output.
traces=traces
# Directory for file descriptor tracking output.
tracked=tracked
# Directory for spar output.
results=results
if [ ! -d "${tracked}" ]
then
mkdir "${tracked}"
fi
"${bindir}trackall" -o "${tracked}" "${traces}"/*
if [ ! -d "${results}" ]
then
mkdir "${results}"
fi
"${bindir}spar" -n "${name}" -d "${tracked}" -o "${results}"
"${bindir}spec2pol" "${results}/${name}_policy_spec.py"
This section describes an example of how to use our policy generation software. We have included instructions for the reader to run this example. Output from each step has been included. Each output file has the same name as the corresponding part of the example.
For our example, we use a set of simple scripts designed to imitate an e-commerce software suite. There are three scripts, each representing a program we would want to design policy for: a server which receives orders over the network, an accounts receivable program which confirms that the order was legitimately paid for, and a shipping program which takes paid orders to be shipped. In addition, we have a client script which places an order. We will walk through the pattern analysis process using these simple programs.
The server is esales.py. Accounts receivable is
acct_rcv.py. Shipping is shipping.py. The client is
salesclient.py.
Requirements: Python 2.2.3 or higher. These instructions assume you will be performing the installation on an SELinux machine. As described above, you may perform analysis of the traces on another machine if you wish.
The polgen tarball includes the SPAR pattern recognition program, the SPAR pre-processor, a SELinux-aware version of strace, and typegen, which facilitates the generation of new types. In addition, we include our example E-Commerce suite.
For this example, we assume that you are installing polgen in your home directory.
$ tar -xzf polgen-0.9.tar.gz
$ cd polgen-0.9
$ ./configure --prefix=$HOME/polgen
$ make
$ make install
$ export PATH=$HOME/polgen/bin:$PATH
Now, we confirm that the programs were installed properly. This commands are optional, but we have included the expected output below for comparison. In particular, we are checking that the machine now has the SELinux-aware strace as well as the version originally installed on the machine.
$ type -all strace
strace is /home/LOGNAME/polgen/bin/strace
strace is /usr/bin/strace
The E-Commerce suite requires a directory which it can freely
change. The
ecomm-config script, which we added to your path, will copy all
of the E-Commerce files into the current directory and configure them
for your machine. NOTE: Do not perform these options in your home
directory, or the file relabeling will not happen
appropriately. (The /usr/share directory is a reasonable
alternative.)
$ su
# cd /usr/share
# mkdir ecomm
# cd ecomm
# ecomm-config
Next, we need to generate the file context and type files for the
E-Commerce suite using typegen, which creates minimal policy
additions for our new program. ecomm-config has installed a
typegen.conf file in the ecomm directory, which we will use to
generate our starting policy. The -i option allows us to specify
the configuration file.
typegen.conf generates allow permissions for several normal
security contexts (run getcon to find out) to transition to the
example executable contexts. If you do not plan to run the example as
user_r:user_t, sysadm_r:sysadm:t, or staff_r:staff_t, you will need to
edit the typegen file.
# typegen -i typegen.conf
Now, we can check to make sure that the installation was successful.
# cat ecomm.fc
/usr/share/ecomm/acct_rcv.py system_u:object_r:ecomm_acct_rcv_exec_t
/usr/share/ecomm/esales.py system_u:object_r:ecomm_esales_exec_t
/usr/share/ecomm/shipping.py system_u:object_r:ecomm_shipping_exec_t
/usr/share/ecomm/paid(/.*)? system_u:object_r:ecomm_paid_orders_dir_t
/usr/share/ecomm/orders(/.*)? system_u:object_r:ecomm_new_orders_dir_t
# ls *.py
acct_rcv.py esales.py salesclient.py shipping.py
Last, we need to incorporate ecomm.te and ecomm.fc in
the running policy. Let $a represent the path to your
installed policy sources. Under FC2, this will be
/etc/security/selinux/src/policy. Under FC3, this will either
be /etc/selinux/targeted/src/policy (by default) or
/etc/selinux/strict/src/policy (if you have switched to the
optional strict policy).
On FC3, we can use the following commands:
# a=/etc/selinux/targeted/src/policy
# cp ecomm.te $a/domains/program
# cp ecomm.fc $a/file_contexts/program
# pushd $a
# make reload
# /usr/sbin/setfiles file_contexts/file_contexts /usr/share/ecomm
We need to perform an analysis of the programs' behavior. As part of
the proprocessing script, we use the strace program to tell us
all of the system calls the program makes during its
run. strace only tracks the program's behavior during a
particular run, rather than its potential behavior, so for complex
programs we need to run through a range of typical activities while
tracing the program. For example, when tracing a web browser we would
want to not only visit a few websites, but also make sure to change
the browser's configuration and use standard plugins. Formally,
strace performs dynamic, not static, analysis, so we need to
execute all code paths. However, for this simple example, we don't
need to worry about thorough testing.
For the example, we will need to run strace on each
important segment of the E-Commerce suite: the e-sales server,
accounts receivable, and shipping. We ignore the client, because we
expect it to normally run on a different machine than the servers and
are not trying to create the client machine policy.
# pushd
# mkdir traces
# strace -fX -o traces/esales.py ./esales.py &
Running the client will give us a sample order.
$ ./salesclient.py
Now, we kill the esales process. Normally, a server would run indefinitely, but we don't need the server any longer, now that we have an order. Next, trace accounts receivable and shipping. In normal operation, these might be executed with a cron job.
$ fg; C-c
$ strace -fX -o traces/acct_rcv.py ./acct_rcv.py
$ strace -fX -o traces/shipping.py ./shipping.py
The trackall program is used to reduce the strace output
into a form that can be used by the spar pattern recognizer.
$ mkdir spar-data
$ trackall -o spar-data traces/*
The .tracked files in spar-data contain lists of system
resources along with information about the permissions requested and
relevant security contexts. These will be our input to the pattern
detector. Sample .tracked files are included.
The spar pattern detector identifies patterns in the system
calls of a program or set of programs. These patterns demonstrate
relations between programs, and describe interactions between programs
and system resources. Many patterns will have security policy
implications, which will help the user generate a secure policy for
the program.
When running spar, you will need an input directory which
contains all of your .tracked files, but nothing else. In our example,
we will use the existing /usr/share/ecomm/spar-data
directory. The -n option specifies the program or suite name to be
used for some output files.
# mkdir spar-results
# spar -n ecommerce -d spar-data -o spar-results
Now, spar-results will contain output files showing any
patterns spar has found in the
input. ecommerce_policy_spec.py is a Python script which will
generate a new .te file with permissions based on the patterns
spar detected. The user can add or remove permissions from this
file at the pattern level, or modify the resulting .te file. There
will also be three HTML files, PolicyHelp.html,
Security-Context.html, and Pattern-Instances.html, and
an associated images directory. These files describe spar's
findings for the user. Finally, there will be an xml file,
ecommerce.xml, which will eventually serve as input to
an optional viewer.
Sample output files are attached.
spar produces three HTML output files, each containing a different
view on spar's findings.
PolicyHelp.html lists all resources used by the program, with
annotations describing which patterns the resource matches, and what
role the resource plays within a given pattern. Resources
which did not match any pattern are also listed. A resource
described as [security context]_INSTANCE indicates that spar-preprocess
detected that some process with context [security context] but no traced
execution attempted to access some other resource.
PatternInstances.html lists all patterns spar
detected. The resources which matched each pattern are listed, along
with their roles within the pattern. The listings are grouped by
category; for example, several different configuration file recognition
patterns are grouped under Config File.
SecurityContexts.html lists each security context which
shows up in the spar-preprocess output, along with the resources which
were observed to have that context.
The primary use of the spar output is .te file generation.
Eventually, we will also offer an optional graphical program for visualizing
the results.
Normally, before creating the .te file from the spar results,
the user would edit the recommended policy generation script. Because
the script generates allow statements from patterns, the user can
describe his desired policy and any changes he wishes to make to
spar's recommendations at a more abstract level than individual
permissions.
To create a .te file with the allow statements spar
recommends, we use the spec2pol program.
# spec2pol spar-results/ecommerce_policy_spec.py
This will generate a current.te file. A sample is included.