donderdag 17 september 2009

AVC Denials: Example

SELinux logs policy violations to /var/log/audit/audit.log if audit is installed and enabled. If audit is
not installed or enabled, than SELinux sends policy violation notices to dmesg or /var/log/messages.

The policy violations that SELinux logs are called AVC denials. AVC is an abbreviation for Access Vector
Cache. Which is the SELinux cache with Access Vectors. Access vectors are the rules that govern access.

Reading AVC denials properly helps troubleshoot issues. In this article i will talk about, and highlight
some of the information you can retrieve from AVC denials. I will also touch on some of the tools that
assist in listing, parsing and translating SELinux Access Vector Cache denials.

Example of a AVC denial:

avc: denied { getattr } for pid=7604 comm="firefox" path="/usr/lib64/firefox-3.5.3/firefox" dev=dm-2 ino=1311607
scontext=dgrift_u:dgrift_r:gwibber_t:s0-s0:c0.c1023 tcontext=system_u:object_r:mozilla_exec_t:s0 tclass=file

The line above provides much information about what has been denied:

1. What process was denied access.
2. What domain type did the source process operate in when it was denied access.
3. What object or subject was the source process denied access to.
4. What was the object/subject type of the target.
5. What permission was denied.
6. What is the class of the target.
7. What was the process identity of the source.
8. What was the inode number of the target object.
9. What happened.

Security is about managing interaction. Interaction has a source and a target. Interaction involves atleast
a subject as a source (an interacting party) and a subject or object as a target. The target of the
interaction. Subjects are interacting entities, and object non-interacting entities. Subjects can interact
with object, but subjects can also interact with other subjects.

The target class in a AVC denial tells us what the class (origin) of the target in an interaction is.
A source of a interaction is always a subject (interacting entity). Object can not interact and thus can
never be a source of an interaction.

Lets try and connect the dots and see if we can make sense of the example AVC denial above. We will try to
answer each of our 9 questions in the check list:

1. What process was denied access.

comm="firefox" shows use the name of the command that was run. The firefox program was denied access.

2. What domain type did the source
process operate in when it was denied access.

scontext=dgrift_u:dgrift_r:gwibber_t:s0-s0:c0.c1023 shows that the source firefox was operating with the
gwibber_t domain type. The type is the third field in the security context tuple.

3. What object or subject was the source process denied access to.

path="/usr/lib64/firefox-3.5.3/firefox" Shows what the target of the source in this interaction was.

4. What was the object/subject type of the target.

tcontext=system_u:object_r:mozilla_exec_t:s0 shows the type of the target.

5. What permission was denied.

{ getattr } Shows the syscall (permission) that was denied.

6. What is the class of the target.

tclass=file shows that the class of the target in our interaction was file.

7. What was the process identity of the source.

pid=7604 shows that the process id of the source of our interaction was 7604

8. What was the inode number of the target object.

ino=131160 shows that the inode number of the target object in our interaction was 131160.

9. What happened.

denied shows that the particular Access Vector was denied.

We have all the detail that we need to established *what* happend.

1. The command /usr/bin/firefox was executed but some interacting entity.
2. This command was executed with the gwibber_t domain type.
3. The target of the source /usr/bin/firefox was /usr/lib64/firefox-3.5.3/firefox
4. The type of the target was mozilla_exec_t
5. The source /usr/bin/firefox that operated with the gwibber_t domain type was denied the "getattr"
syscall on the target /usr/lib64/firefox-3.5.3/firefox that had type mozilla_exec_t.
6. The class of the target /usr/lib64/firefox-3.5.3/firefox is a file (the target is a file object)
7. The process of /usr/bin/firefox had the process id of 7604 when this Access vector occured.
8. The inode number of the target file object is 131160
9. Access was denied.

These are the SELinux facts:

the /usr/bin/firefox command was denied to get the attributes of the /usr/lib64/firefox-3.5.3/firefox file
source domain type gwibber_t was denied get attribute of a file object with type mozilla_exec_t

What this means is that there was no rule to allow this access, thus access was denied.

From here on out things get less obvious:

We know some facts but this has raised other questions:

1. Are the types of the source and target correct?
2. We know what was denied but we dont know why.
3. Should we allow this access?
4. Does it signal intrusion?
5. If we allow it access what would be the best way to do it.
6. What are the problems if we do it the other way?

The reason that these questions are harder to answer is because it depends on the policy that is created by
the policy author. But if you see an AVC denial we can usually narrow the cause down to:

a. The source and/or the target is mislabelled (wrong type)
b. It is a bug in policy.
c. Intrusion was detected and prevented.

So let's try to answer all these questions:

1. Are the types of the source and target correct?

This is the first thing we must verify. If the types are incorrect than we must correct them first to be able to learn the real reason
about what happend. Objects sometimes get mislabelled. For example if created the object whilst you had SELinux disabled and forgot to
restore the context. Another reason might be that you have moved the file from another location as opposed to copying it, and forgot
the restore the context.

How do we determine whether the types are correct? Well the answer is that we have to dig into some of the properties of the policy.
We have to put ourselves into the shoes of the policy author.

To verify whether the type of the source (gwibber_t) is correct we have to ask ourselves which policy module owns this type?
This is a hard question to answer. Really the only way to figure this out is to grep for the gwibber_t type in the source of the
policy. In this case there is a policy module installed called gwibber.

For example:

grep -r "type gwibber_t" Modules/

We are looking for the declaration of the gwibber_t type. Types are usually declared in files with .te suffixes (type enforcement
source policy files)

So we could narrow our grep a bit:

grep -r "type gwibber_t" Modules/ | grep "\.te"

Modules/gwibber.te:type gwibber_t;
Modules/gwibber.te:type gwibber_tmpfs_t;

The type is declared in the gwibber.te source policy type enforcement file. We can now grep this file for the policy_module
declaration to figure out what the name of the module is:

grep policy_module Modules/gwibber.te
policy_module(gwibber, 0.0.1)

The policy module name is gwibber and the version number is 0.0.1, Now we can determine whether this module is installed:

sudo /usr/sbin/semodule -l | grep gwibber
gwibber 0.0.1

The module is installed, we know that the type gwibber_t is owned by the gwibber module.

Now we should figure out what the type of the firefox command is. the firefox command is located in /usr/bin/firefox.
We can use ls -alZ /usr/sbin/firefox to determine the type of this command:

-rwxr-xr-x. root root system_u:object_r:bin_t:s0 /usr/bin/firefox

The type of the firefox command is bin_t. This type has a special property that is specific to the policy model. You could look up the
properties of this type the same way that we are currently looking up the properties of type gwibber_t.

But to not overly complicate things i will explain the main property of the bin_t type.

The bin_t type is a generic type for executable files in bin and sbin directories. These commands get run with the domain type of the
subject that executed the command. So if a process that was operating with the gwibber_t domain type executed a command with the bin_t
type, than that command would run with the gwibber_t domain type.

With this in we have to figure out whether processes with the gwibber_t domain type are allowed to execute files with the bin_t type:

sudo sesearch --allow -s gwibber_t -t bin_t -c file -p execute
Found 1 semantic av rules:
allow gwibber_t bin_t : file { ioctl read getattr lock execute execute_no_trans open } ;

The sesearch command queries the policy store and looks if there is a rule which allows the source gwibber_t domain type to execute
target objects of the files class with type bin_t.

A line is returned confirming that this is allowed. This tells us that the source in our interaction is likely correclty labelled.
This is what happened. Some process that run with the gwibber_t domain type ran /usr/bin/firefox which has the bin_t type causing the
firefox command to run with the gwibber_t domain type.

Now we need to determine whether the type of our target is correct. In our interaction that fortunatly is pretty easy.
We know the path of our target: /usr/lib64/firefox-3.5.3/firefox
We can run the matchpathcon command to see what type is defined for this location and if that defined type corresponds to the target
type in our avc denial: mozilla_exec_t.

sudo /sbin/matchpathcon /usr/lib64/firefox-3.5.3/firefox
/usr/lib64/firefox-3.5.3/firefox system_u:object_r:mozilla_exec_t:s0

This confirms that the labelling in the interaction is correct for both source and target.

Sometimes however, the full path of the target is not shown in a avc denial. In that case you can use the inode number to find the
full path:

find / -inum 131160
/usr/lib64/firefox-3.5.3/firefox

2. We know what was denied but we dont know why.

This is another hard question to solve. We are no psychics. We cannot read the mind of the policy author.
We can try:

Should gwibber be able to run firefox? It should be able to run the default browser yes but in this case (the case where i am the
policy author of the gwibber policy module) it was decided to not allow this funcionality. It is obvious that the gwibber_t domain
type was not allowed the access/see (get attributes) the mozilla executable file with type mozilla_exec_t. So either that was done on
purpose or it is a bug in the policy.

3. Should we allow this access?
3. Should we allow this access?
4. Does it signal intrusion?
5. If we allow it access what would be the best way to do it.
6. What are the problems if we do it the other way?

Another tough question. if we allow gwibber_t to get attributes of files with type mozilla_exec_t it will probably want more after
that. Chances are that gwibber wants to execute the file (run firefox), since gwibber is designed to open pages in the default
browser.

If we want gwibber to be able to open the browser, do we want to allow gwibber_t to run the browser with the gwibber_t type or should
we lets gwibber_t domain transition to the mozilla_t domain type? Well my personal opinion is to domain transition where ever possible
but it depends on the situation. In this case a domain transition from gwibber_t to mozilla_t via mozilla_exec_t would likely be the
best decision. However this requires that policy is written manually to make it do what we want it to do.

But what if we just want to allow this single access vector? We could use the audit2allow tool to translate the avc denial into policy
language and to create a module. Than we could load the created policy module into the policy store with the semodule command.

echo "avc: denied { getattr } for pid=7604 comm="firefox" path="/usr/lib64/firefox-3.5.3/firefox" dev=dm-2 ino=1311607
scontext=dgrift_u:dgrift_r:gwibber_t:s0-s0:c0.c1023 tcontext=system_u:object_r:mozilla_exec_t:s0 tclass=file" | audit2allow -M
mygwibber; sudo semodule -i mygwibber.pp

Or we could do it ourselves:
echo "policy_module(mygwibber, 0.0.1)" > mygwibber.te;
echo "require { type gwibber_t, mozilla_exec_t; }" >> mygwibber.te;
echo "allow gwibber.te mozilla_exec_t:file getattr;" >> mygwibber.te;
make -f /usr/share/selinux/devel/Makefile mygwibber.pp
sudo semodule -i mygwibber.pp

So:

a. The source and/or the target is mislabelled (wrong type)

The types were correct.

b. It is a bug in policy.

It is a bug in policy because we determined that it is usually behaviour for gwibber to try to run the default browser to display
pages. Either we should allow it gwibber to run the browser (be it with the gwibber_t domain type or by domain transition with the
mozilla_t domain type) or we should make sure that no AVC denials are displayed when gwibber_t tries to access the mozilla executable
file with type mozilla_exec_t.

The rule that i am going to implement is this:

dontaudit gwibber_t mozilla_exec_t:file getattr;

Which says if domain type gwibber_t tries to get attributes of files with type mozilla_exec_t than "dontaudit" which means do not
print an avc denials (e.g. silently deny this)

That is just my personal preference. Its not something fixed. It is my security decision, whether good or bad.

c. Intrusion was detected and prevented.

No not really an intrusion since gwibber is designed to open pages in the default web browser which is firefox. So it is expected
behaviour. However i dont want to allow it. But i dont want to log the AVC denial when it happens either because its not important.

woensdag 16 september 2009

A perspective on SELinux

Many people think SELinux is complicated. SELinux is actually beautifully simple if you keep in mind that it
allows you to manage security very granular in computer systems which are very complex.

In this article i will try to explain the basics of SELinux. The things you need to know to find your
way around the SELinux environment.

SELinux can roughly be categorized in a few separate parts (ordered by importance):

1. The SELinux framework.
* 2. The tools to manage SELinux.
* 3. The policy.

In this article i will talk about The SELinux framework and the Type enforcement security model.

Knowledge of the SELinux framework is fundamental. If you are familiar with this it will enable you to
find your way around the rest.

Knowledge of the different SELinux security models is also important in this part i will talk about how
the Type enforcement security model fits into the SELinux Framework.

To learn about SELinux you have to know a bit about security and about computer systems.

What is security? Security is managing parties in an interaction. So for example if you want to secure a
human sitting on a chair. You have to manage the human and the chair. The human interacts. this is
called a subject, the chair does not interact and this is called an object. You could create policy that allows
the human to sit on the chair but not stand on it. Standing on it may cause it to break.

How do computer systems work? Computer systems are similar. processes are like humans. We call them
agents. A process therefore is a subject just like the human in my chair example. Processes interact. A
file in a computer system does not interact. The subject interacts with it. A file is a object. In a
computer system there are many classes of objects just like there are many kind of classes of object in
real life. My example was a chair but it could have been a bed or a bike etc. In a computer system a
object could be a file or a network port. Generally keep in mind that subjects interact and object get
interacted with.

So simplified:
Real life: human, chair, sit
Computer system: process, file, read

Humans can be categorized in many classes, the most obvious is man and woman but there are many types of
different humans. Processes in a computer system can also be categorized in many classes, for example a
process of a user or a process of a program.

Chairs can also be categorized in many classes. Theres rocket chairs and theres oother chairs as well,
but they are all chairs and objects. Objects in computer systems can also be categorized. There are
files and directories etcetera.

If you want to manage all these subjects and objects than you will want to categorize them. So that you
can create policy for each.

Subjects interact, objects dont. Lets look at some policy for the examples i gave.

real life:
allow man chair:rocket_chair sit;

computer system:
allow user file:dir read;

So in the real life example we allow a subject: human of the type: man to sit on a chair that is of the
class rocket_chair.

In the computer system example we allow a subject: process of the type user to read a file that is of
the class dir.

Our rule start with allow to signal that we want to allow the rule that follows, than follow our source
of the interaction. Which is always a subject since subject interact and object do not. Next is the
target. targets can be either subject or objects. subjects can interact with other subjects. for example
a man talking with a woman. Next is the class of the target. in our man/woman interaction the class
would of the target human would be woman. The last part defines the permission. What interaction is
allowed? in our man/chair example the man is allowed to site on a rocket_chair in our computer system
example the user process is allowed to read a dir. In our recent man talks to woman example we allow a
man to talk to a woman.

So back to SELinux. How does SELinux relates to all this. SELinux is for a large part in the kernel. It
is a framework. That means that SELinux provides us with some attributes so that we can create policy to
define what may and what may not. The attributes that SELinux provides are classes and permissions.
SELinux knows the classes of the parties involved in interaction in a computer system. It knows
subjects and the different classes of objects. SELinux also knows how subject interact with the
different object. In the real life example: SELinux knows theres a human interacting with a chair. It
knows the chair is a rocket chair and it know in what ways humans interact with chairs (sit for example)

So the framework provides us with the attributes to create rules. What it cannot do is make further
destictions between different subjects and objects. And to be able to manage everything we must make
distinctions as much as possible. This is what policy authors do. They make categorize sources and
targets in an interaction. for example. SELinux knows a human wants to site in a chair. It even knows it
is a rocket chair. But what if we want to make a destinction between a yellow rocket chair and a red
rocket chair? We want to be able to allow the human to site in the red rocket chair but not the yellow
one. SELinux framework does not know the color, we do. This is where types come in.

Policy authors assign types to subjects and objects. so in the real life example:

allow human chair:rocket_chair sit;

allow human_man_type red_chair_type:rocket_chair sit;

In the computer system:

allow process file:dir read;

allow user_process_type home_file_type:dir read;

Types allow us to further categorize the parties in an interaction.

If sufficient for now to know that the SELinux framework provides us with the classes and permission
attributes and that it allows us the further categorize the source and target in an interaction, be it
subjects or objects.

Type enforcement is a model where policy is enforcement for interaction between the types of the parties
involved. The types can be defined by the policy author and the best types depend on the environment.

In a computer environment you might want to make a destinction between a log file and a library file, a
program or a user. In a real life environment you might want to make a destinction between man or woman,
red rocket chair or yellow rocket chair. It depends on what colors rocket chairs exist in you
environment. Types enable us to define the properties of our environment.

By default all interaction is forbidden. if we want to allow something we have define what is allowed.
If there are many types and classes of parties in interaction in an environment you might be able to
imagine to amount of rules required to manage all this. For now it is sufficient to know that there are
also ways to group or tag different types.

If you want a human to be able to sit on all colored rocket chairs you could for example tag the
red_chair_type and the yellow_chair_type to be colored_chair_types and use the tag to make one single
rule for both colored chairs.

allow human_man_type colored_chair_types:rocket_chair sit;

So that is a very important thing to understand about SELinux and security in general. The enforcement
of types is the most important security model of SELinux.

Besides the "allow source target:target_class permission;" rules, there is another thing to understand
and that is called a type transition. You can make one type transition to another type.

For now it is suffice to know that subject and object types can be triggered to change. Subject types
can change via rules that define what should happen if a process executes a file and object
types can transition via rule that define what should happen if a file is created under a certain
parents type.

Type transitions help you futher categorize parties which will let you define rule for types in certain scenarios.

This is the basics about SELinux. Types are configured by policy authors. The have special meanings and those meanings can vary per
policy. So the only thing that really always applies are classes and permissions they stay the same. Types are defined by humans and
to learn what a certail type is allowed you would have to reference the policy to determine that.

And that is want you we are often confronted with, types. rules that govern how one type can interact with another. What we dont know
is what a certain type of a subject is supposed to be allowed to do to a certain type of a object.

These things can be figured out by referencing the policy and asking yourself the question what is the meaning of the type? what are
its properties? This is what makes SELinux environments complex because policy is based on a policy authors vision on a system. And
that vision may differ per policy model and environment.

SELinux itself is not complicated but if you want to manage a complex system you will have to create many different types and thats
where SELinux gets complex. If you have a simple system to manage than SELinux will also be simpeler. If you have a simple security
goal on a complex system you may also be able to implement a simpler policy that is targeted towards just reaching your simple
security goal.

Eventually its all just subjects, objects, classes and permissions when it comes to the SELinux framework and the type enforcement
security model.

The more granular the policy to govern how subject can interact with objects gets,the complexer selinux gets. But this is the strenght
of SELinux: it allows you to define very granular what is allowed and what not in a system.

Blame the policy author and the policy for the complexity of managing your Security-Enhanced Linux ( i bet the policy author will
blame Linux ;) )

A quick note about the tools:

What are the tools for:

labeling objects
parsing access vector denials
translating access vector denials to policy
finding suggestions to solutions for access vector denials
finding what type a object should have
changing types of objects
restoring types of objects
searching rules in the policy database
mapping linux logins to subject types

donderdag 10 september 2009

Some SELinux experiences that i want to share with you:


Disclaimer: I am just thinking out loud here, and i am sure that in some cases i do not fully understand the complexity or the underlying ideas of, and behind the issues that i am about to describe.

1. (not fedora specific)
User space processes own files on tmpfs for pulseaudio. These user space processes want to read (and unlink) each others pulseaudio files on tmpfs. To facilitate this, it requires much policy and also by allowing a user space process to read another user space processes pulseaudio tmpfs files , you also give it access to the user space process non pulseaudio tmpfs files. which might not be desired.

maybe somehow we can implement a attribute for user space processes pulseaudio files on tmpfs. and/or create a generic interface for this interaction.

3. (fedora specific)
xserver policy has been modified and xserver_user_x_domain_template and xserver_x_domain_template have been added. These templates could be used instead of xserver_user_client and xserver_common_app.

By calling these templates other xserver related policy in the domain that call it can for a large part also be removed. The interfaces mentioned above include most of the required xserver policy for user and application processes to function.

There are some notable exceptions:

xserver_rw_xdm_home_files

Also it appears that the interfaces mentioned above were designed with mls policy in mind. To be able to enable xserver object manager in a way that could benefit targeted policy i think a solution could be found so that xserver policy can be easily extended to provide a basic multi purpose useable policy for targeted as well ( maybe create interfaces for the various scenarios ) so that interfaces (or maybe tunable policy) can be called to make xserver object manager work in a basic form and/or specific form in targeted policy.

So that the admin can easily extend xserver policy for his custom needs without having to write local policy himself or having to implement his own custom interfaces, at least as much as possible.

An example of stuff that currently has no policy implemented but in many cases is required is for example the functionality to change mouse button (for left handed people) and the use of acceleration (3d)

Also we should keep in mind that there is a allow_write_xshm boolean that probably should be used where ever required instead of allowing access to this by adding fixed policy.

My point is that i think xserver object manager could at least to some extend be usable in a targeted policy, and that it could be extendible. Currently in fedora there is no easy way to make openoffice work nice with XACE. I cannot extend its policy due to 'not within scope issues' (user domain prefixes). The java SELinux implementation suffers similar issues.

3. (not fedora specific)
This also brings me to staff and user domains. These domains do not have access to some devices (cannot rw to dri, cannot rw to wifi, webcam etc) maybe we should implement some booleans for this with a $1. e.g. userdom_$1_use_dri etc. or maybe create users domains that add this functionality. I think this is a requirement to makes confined domains acceptable for day-to-day GUI use. Also the allow_execmem boolean is a bit too coarse. Lets face it we are not close to a working none execmem/execstack environment yet. For example nautilus requires it, totem, etc. many of these apps run in the user domain. Setting allow_execmem would in my view be overkill to just allow a single user domain execmem permission. allow_$1_execmem, where $1 is a specific user domain would in my view be a reasonable temporary solution. In either case i do not think we should just ignore the issue.

The "easy" access to execmem and devices like dri are in my view important to help make confined user domains usable for the general public in a GUI environment.