+ =
1.
+ SELinux Policy Language
+Introduction
+
+By default, Gentoo provides a generic, yet tightly controlled policy whi=
ch is
+deemed a good start policy for the majority of users. However, the purpo=
se
+behind a Mandatory Access Control system is to put the security administ=
rator in
+control. As such, a handbook on SELinux without information on how to wr=
ite
+policies wouldn't be complete.
+
+
+In this chapter, we'll talk a bit about the language behind SELinux poli=
cies and
+give some pointers on how to create your own policies, roles, etc.
+
+Building a SELinux Mod=
ule
+
+First, before we go into the art of SELinux policy writing, let's first =
make a
+small SELinux module with a rule we can test, build the module and see i=
f things
+work. Although these steps are fairly easy, they are important nonethele=
ss.
+Modifying the SELinux policy as offered by Gentoo is best done through
+additional SELinux policy modules. Only when the core policy (the base p=
olicy)
+is not to your liking should you see on using a totally different policy=
.
+
+
+Let's start with a skeleton for a policy module we'll call testmod.
+
+
+Code Listing1.1: Poli=
cy module skeleton |
+
+policy_module(testmod, 1.0.0)
+ |
+
+
+Yes, that's it. But as you can see, it is fairly empty. So let's add a r=
ule that
+allows a regular user (in the user_t domain) to read ebuild files (of ty=
pe
+portage_ebuild_t).
+
+
+Code Listing1.1: Poli=
cy module testmod |
+
+policy_module(testmod, 1.0.0)
+
+require {
+ type user_t;
+ type portage_ebuild_t;
+ class file { read open getattr };
+ class dir { read search open getattr };
+}
+
+allow user_t portage_ebuild_t:file { read open getattr };
+allow user_t portage_ebuild_t:dir { read search open getattr };
+ |
+
+
+As you can see, something as simple as allowing a user to read a file re=
quires
+quite a few privileges. The directory privileges are needed to allow a u=
ser to
+navigate through the Portage tree structure whereas the file privileges =
are
+needed for a user to be able to access and open the ebuilds. Save this f=
ile as
+testmod.te.
+
+
+To build the policy and convert it into the binary module that we can lo=
ad into
+the SELinux policy store, we can use the Makefile available in
+/usr/share/selinux/strict/include (substitute strict with the
+SELinux policy type you are using).
+
+
+Code Listing1.1: Buil=
ding a binary policy module |
+
+$ make -f /usr/share/selinux/struct/include/M=
akefile testmod.pp
+ |
+
+
+The filename (testmod.pp) is the=
destination binary SELinux module
+name. The Makefile will automati=
cally look for the
+testmod.te file you have in the =
working directory.
+
+
+As a result, you should now have a file called testmod.pp. This
+module file can now be loaded in the SELinux policy store as follows:
+
+
+Code Listing1.1: Load=
ing a binary module |
+
+# semodule -i /path/to/testmod.pp
+ |
+
+
+Congratulations! You have now build your first SELinux policy module. If=
you
+want to disable it, remove it through s=
emodule -r testmod.
+
+
+This method of building a policy (using the Makefile and
+semodule) is something that you =
will need to do every time you want to
+update the SELinux policy on your system. The contents of the policy how=
ever
+does change as we will see in the rest of this document.
+
+Getting the SELinux Po=
licy Interfaces
+
+To streamline policy development, the SELinux policy based on the refere=
nce
+policy uses interfaces to access privileges within a module. If you have=
built
+selinux-base-policy with USE=3D"doc" then this information is
+available at
+/usr/share/doc/selinux-base-policy-<=
version>/html. It is
+recommended to have this information at hand, since most policy
+development/updates will be done through the interfaces offered by the p=
olicy.
+
+
+If you are just interested, you can also find these interface definition=
s online. Mind =
you though,
+the online resource is only the reference policy and might differ a bit =
from the
+policy available within Gentoo.
+
+Using Policy Interface=
s
+
+Using the policy interfaces allows you to update the policy with more re=
adable
+functions. For instance, to allow the user_t domain to call and use Port=
age
+applications, the module could look like so:
+
+
+Code Listing1.1: Exam=
ple policy to allow user_t to use portage |
+
+policy_module(testmod, 1.0.0)
+
+require {
+ type user_t;
+ role user_r;
+}
+
+portage_run(user_t, user_r)
+ |
+
+
+Of course, this makes the user_t domain much more privileged than the pr=
eviously
+defined rules to read ebuild files: it allows the user to call portage, =
update
+the system, etc. Of course, the user still requires the proper regular L=
inux
+permissions (so he needs to be part of the portage group or become root)=
.
+Needless to say, we do not recommend to grant this to a regular user ;-)
+
+=
1.
+ Full SELinux Policy Modules
+Checking Out an Isolat=
ed Module
+
+With the above in mind, we can now go one step further and investigate a=
full
+policy module, with both the type enforcement rules (.te file),
+file contexts (.fc) and interfac=
es (.if).
+
+
+You should know that writing a module requires you to get intimate with =
the
+application. It isn't a matter of just hoping for the best: as a securit=
y
+administrator, you will be responsible for defining what accesses are al=
lowed
+and which not. If you forget one, the application might break under the =
users'
+hands. But if you add too much, you might grant privileges that can be a=
bused
+later on. And it will be a lot more difficult to track and remove privil=
eges
+later as you will be hesitating if the privilege is needed or not.
+
+
+In this section, we will not divulge in how to write one. We have an exc=
ellent
+Gentoo Hardened SELinux
+Development resource that guides you in that. However, we will look =
into
+such a full module to explain the other aspects of policy development.
+
+Type Enforcement File<=
/a>
+
+The .te file we wrote earlier is=
a type enforcement file.
+Its purpose is to define the access rules related to the module that you=
are
+building, but also - and more importantly - define new types (or even ro=
les).
+
+
+The example below is a snippet from a module for the skype application.
+
+
+Code Listing1.1: Snip=
pet from skype.te |
+
+policy_module(skype, 1.0.0)
+
+type skype_t;
+type skype_exec_t;
+application_domain(skype_t, skype_exec_t)
+
+type skype_home_t;
+userdom_user_home_content(skype_home_t)
+
+manage_dirs_pattern(skype_t, skype_home_t, skype_home_t)
+manage_files_pattern(skype_t, skype_home_t, skype_home_t)
+ |
+
+
+In the above example, three new types are declared: skype_t (which will
+be used for the application), skype_exe=
c_t (which is the label given to
+the application binary) and skype_home_=
t (which will be used for the
+users' ~/.Skype location). Also,=
the skype_t domain is given
+some privileges with respect to the sky=
pe_home_t label (manage
+directories and files).
+
+File Context File<=
/p>
+
+In the .fc file (which stands fo=
r file context file) the
+module's resources (files, directories, sockets, ...) are defined. Once =
the
+module is loaded, these rules are added so that file system relabeling w=
ill put
+the correct context on the files.
+
+
+The example below is a snippet from the skype modules' file context file=
.
+
+
+Code Listing1.1: Snip=
pet from skype.fc |
+
+HOME_DIR/\.Skype(/.*)? gen_context(system_u:object_r:skype_home_t,s0)
+/opt/skype/skype -- gen_context(system_u:object_r:skype_exec_t,s0)
+/usr/bin/skype -- gen_context(system_u:object_r:skype_exec_t,s0)
+ |
+
+
+The format of the file context file has the following syntax:
+
+
+ -
+ The regular expression that matches the file(s) and directorie(s) af=
fected
+ by that line
+
+ -
+ An optional identifier to differentiate the type of files (file, dir=
ectory,
+ socket, symbolic link, ...)
+
+ -
+ A gen_context line that cont=
ains the context to assign to the file(s)
+ and directorie(s)
+
+
+Interface File
+
+In the .if file (for interface file) interfaces are declared
+which can be used by other modules. It is through interfaces that a nice=
ly
+defined policy can be built on top of other, existing policy modules.
+
+
+One interface could be to allow users to call and execute an application=
. For
+instance, the following interface can be found in the skype module.
+
+
+Code Listing1.1: Snip=
pet from skype.if |
+
+interface(`skype_role',`
+ gen_require(`
+ type skype_t, skype_exec_t, skype_tmpfs_t, skype_home_t;
+ ')
+
+ role $1 types skype_t;
+
+ domtrans_pattern($2, skype_exec_t, skype_t)
+
+ allow $2 skype_t:process { ptrace signal_perms };
+
+ manage_dirs_pattern($2, skype_home_t, skype_home_t)
+ manage_files_pattern($2, skype_home_t, skype_home_t)
+ manage_lnk_files_pattern($2, skype_home_t, skype_home_t)
+
+ relabel_dirs_pattern($2, skype_home_t, skype_home_t)
+ relabel_files_pattern($2, skype_home_t, skype_home_t)
+ relabel_lnk_files_pattern($2, skype_home_t, skype_home_t)
+
+ ps_process_pattern($2, skype_t)
+')
+ |
+
+
+Through this skype_role, we can =
then allow users to call skype, as can be
+found in the unprivuser.te file =
(which defines the user_t domain):
+
+
+Code Listing1.1: Snip=
pet from unprivuser.te to call skype |
+
+optional_policy(`
+ skype_role(user_r, user_t)
+')
+ |
+
+=
1.
+ Using audit2allow
+Introduction
+
+When reading online resources on SELinux, you will notice that there are=
many
+references to a tool called audit2allow=
. This tools' purpose is to read
+AVC denial messages from the audit log file and transform them into a po=
licy
+module that you can load. The advantage is that it makes it a lot easier=
to
+write policies. The downside is that the output (unless you use the -R
+option) is not usable for the Makefile<=
/span> we used earlier to build
+modules.
+
+
+Another disadvantage is that the tool does not intelligently cope with c=
hanges.
+It blindly accepts denials and treats them as if they need to be allowed=
, rather
+than investigate if no other context should be given to the file, etc.
+
+Using audit2allow<=
/p>
+
+Using audit2allow is pretty stra=
ightforward. You send it the denials you
+want to fix and store the result in a .=
te file. You then convert it
+into an intermediary format which can then be translated into a .pp
+file for final loading by semodule.
+
+
+For instance, to catch all denials and transform them into allowed state=
ments
+from firefox-related denials:
+
+
+Code Listing1.1: Gene=
rate a new policy using audit2allow |
+
+# grep firefox /var/log/avc.log | audit2allow=
-m firefoxmod > firefoxmod.te
+# checkmodule -m -o firefoxmod.mod firefoxmod=
.te
+# semodule_package -o firefoxmod.pp -m firefo=
xmod.mod
+# semodule -i firefoxmod.pp
+ |
+
+ |
+