- Exploring SE for Android
- William Confer William Roberts
- 1764字
- 2021-07-23 20:37:35
Putting it together
SELinux labels are quite flexible and sometimes complex. It's often beneficial to start with a contrived example that focuses on type enforcement. Later, we can add additional fields later as the need for finer granularity becomes more apparent. Conveniently, you can project this model to scenarios in everyday life to provide some sense of tangibility to the material. Dan Walsh, a prominent SELinux figure, posted a blog post using pets as an analogy. Let's continue on with that premise, but we will make some modifications as we go and define our own examples. It's best to start with simple type enforcement as it is the easiest to understand.
Note
You can read Dan Walsh's original blog post introducing the pet analogy at http://opensource.com/business/13/11/selinux-policy-guide.
Suppose we own a cat and a dog. We don't want the cat to eat dog food. We don't want the dog to eat cat food. At this point, we have already identified two subjects, a cat and a dog, and two targets, cat food and dog food. We also have identified an access vector, eating. We can use allow rules to implement our policy. Possible rules could look like this:
allow cat cat_chow:food eat; allow dog dog_chow:food eat;
Let's use this example to start and define a basic syntax for expressing the access controls we would like to enforce. The first token is allow
, stating we wish to allow an interaction between a subject and a target. The dog is assigned the type, dog
, and the cat, cat
. The cat food is assigned the type cat_chow
, and the dog food, dog_chow
. The access vector in this case is eat
. With this basic syntax, which is also valid SELinux syntax, we restrict the animals to the food they should eat. Notice the :food
annotation after the type. This is the class field of the target object. For instance, there might also be dog_chow
treat
and cat_chow
classes that could indicate our desire to allow access to treats in a fashion that is potentially different from the way we allow access to foods that are not treats.
Let's say we get two more dogs, and our scenario has three dogs. The dogs are of different sizes: small, medium, and large. We want to make sure none of these new dogs eat others' food. We could do something like create a new type for each of the dogs and prevent dogs from eating the food of other dogs. It would look something like this:
allow cat cat_chow:food eat; allow dog_small dog_small_chow:food eat; allow dog_medium dog_medium_chow:food eat; allow dog_large dog_large chow:food eat;
This would work; however, the total number of types would be difficult to manage, and that would continue to grow if we allow the large dog to eat the smaller breeds' food. What we could do is use MLS support to assign a sensitivity to each target or dog food bowl. Let's assume the following:
- The cat's food bowl has sensitivity,
tiny
- The small dog's food bowl has sensitivity,
small
- The medium-sized dog's food bowl has sensitivity,
medium
- The large dog's food bowl has sensitivity,
large
We also need to make sure that the subjects are labeled with the proper sensitivity as well:
- The cat should have sensitivity,
tiny
- The small dog should have sensitivity,
small
- The medium-sized dog should have sensitivity,
medium
- The large dog should have sensitivity,
large
At this point, we need to introduce additional syntax to allow the interactions, since by default, MLS allows everything and TE denies everything. We'll use mlsconstrain
, to restrict interactions within the system. The rule could look like this:
mlsconstrain food eat (l1 eq l2);
This constraint only allows subjects to eat food with the same sensitivity level. SELinux defines the keywords l1
and l2
. The l1
keyword is the level of the target and l2
is the level of the source. Because the rules are part of a whitelist, this also prevents subjects from eating food that does not have the equivalent sensitivity level.
Now, let's say we get yet another large dog. Now we have two large breed dogs. However, they have different diets and need to access different foods. We could add a new type or modify an existing type, but this would have the same limitations that led us to use sensitivities to prevent access. We could add another sensitivity, but it might get confusing that there are large1
and large2
sensitivities. At this point, categories would allow us to get a bit more granular in our controls. Suppose we add a category denoting the breed. Our MLS portion of our label would look something like this:
large:golden_retriever large:black_lab
These could be used to prevent the black lab from eating the golden retriever's food. Now suppose you're surprised with another dog, a Saint Bernard. Let's say this new Bernard can eat any large dog's food, but the other large dogs can't eat his food. We could label the food bowls and the dogs.

The existing mlsconstraint
needs modification. If the Saint Bernard ran out of food and went to the Black Lab's dish, the Saint Bernard would not be able to eat from it since the levels are not equal (Dog:large:saint_bernard, black_lab, golden_retriever
is not the same as dog_chow:large:black_lab
). Remember, the levels are sets, so we need to introduce some notion that if the subjects set dominates the target set, that interaction should be allowed.
This could be accomplished with the dom
keyword:
mlsconstrain food eat (l1 dom l2);
The dominate keyword, dom
, differs from equality, indicating l1
is a superset of l2
In other words, the levels associated with the target, l2
, are among the potentially larger set of levels associated with the subject, l1
. At this point, we are able to keep all the food separated and used however we see fit.
After getting all these dogs, you realize it's time to feed them, so you get a bag of dog food and put some in each bowl. However, before you can add dog food to the bowls, we need some allow rules and labels that will let you. Remember, SELinux is a whitelist-based system, and everything must be explicitly allowed.
We will label the human with the human
label and define some rules. Oh yeah... don't forget to feed the cat, as well:
allow human dog_chow:food put; allow human cat_chow:food put;
We will also need to label human
with all the sensitivities and categories, but this would become cumbersome when we need to add additional dogs, breeds, and breed sizes to our system. We could just bypass the constraint if the type is human
. With this approach, we always trust human
to put the correct food in the appropriate bowl:
mlsconstrain food eat (l1 dom l2); mlsconstrain food put (t1 == human);
Note the addition of put
in the access vectors of the MLS constraint. Viola! The human can now feed his ever-growing pack of animals.
So your birthday rolls around, and you receive an automatic dog feeder as a present. You label the food dispenser, dispenser
and modify the MLS constraints:
mlsconstrain food eat (l1 dom l2); mlsconstrain food put (t1 == human or t1 == dispenser);
Again, we see a need to condense the number of types and get organized to prevent having to duplicate lines. This is where attributes are quite handy. We can assign an attribute to our human
and dispenser
types by first defining the attribute:
attribute feeder;
Then we can add it to the type:
typeattribute human, feeder; typeattribute dispenser, feeder;
This could also be done at type declaration:
type human, feeder; type dispenser, feeder;
At this point, we could modify the MLS statements to look like this:
mlsconstrain food eat (l1 dom l2); mlsconstrain food put (t1 == feeder);
Now let's suppose you hire a maid service. You want to ensure anyone sent by the maid service is able to feed your pets. For that matter, let's let your family members feed them, as well. This would be a good use case for the user capabilities. We will define the following users: adults_u
, kids_u
, and maid_u
. Then we'll need to add a constraint statement to allow interactions by these users:
mlsconstrain food put (u1 == adults_u or u1 == maid_u);
This would prevent the kids from feeding the dogs, but let the maids and adults feed them. Now suppose you hire a gardener. You could create yet another user, gardener_u
, or you could collapse the users into a few classes and use roles. Let's suppose we collapse gardener_u
and maid_u
into staff_u
. There is no reason the gardener should be feeding the dog, so we could use role-based transitions to move the staff between their duties. For instance, suppose staff can perform more than one service, that is, the same person might garden and clean. In this case, they might take on the role of gardener_r
or maid_r
. We could use the role capability of SELinux to meet this need:
mlsconstrain food put (u1 == adults_u or (u1 == staff_u and r1 == animal_care_r);
Staff may only feed the dogs when they're in the animal_care_r
role. How to get into and back out of that role is really the only component missing. You need to have a well-defined system for how the staff can move into the animal care role and transition back out. These transitions in SELinux occur either automatically via dynamic role transitions or via source code modifications. We'll assume that any human entity (gardener, adults, kids) all start in the human_r
role.
Dynamic role transitions work with a two-part rule, the first part allows the transition to occur via an allow rule:
allow human_r animal_care_r;
The role transition statements are as follows:
role_transition human_r dog_chow animal_care_r; role_transition human_r cat_chow animal_care_r;
This would be a good case to attribute the dog_chow
and cat_chow
types to a new attribute, animal_chow
, and rewrite the preceding role transitions to:
typeattribute dog_chow, animal_chow; typeattribute cat_chow, animal_chow; role_transition human_r animal_chow animal_care_r;
With these role transitions, you can only go from the human_r
role to animal_care_r
. You would need to define transitions to get back as well. It's also important to note that you might define other roles. Suppose you define the role gardener_r
, and when someone is in that role, they cannot transition to animal_care_r
. Suppose your justification for this policy is that gardeners might work with chemicals unsafe for pets, so they would need to wash their hands before feeding pets. In such a situation, they should only be able to transition to animal_care_r
from the hand_wash_r
role.
- Web程序設計及應用
- Spring 5.0 By Example
- Visual Studio 2012 Cookbook
- Computer Vision for the Web
- JIRA 7 Administration Cookbook(Second Edition)
- C# 從入門到項目實踐(超值版)
- C#程序設計(慕課版)
- Blockly創意趣味編程
- 從Power BI到Analysis Services:企業級數據分析實戰
- Java程序設計教程
- Mastering Embedded Linux Programming
- Less Web Development Cookbook
- Android初級應用開發
- Python Penetration Testing Essentials
- Python繪圖指南:分形與數據可視化(全彩)