Writing a basic SELinux LPM

I couldn't find a straight forward tutorial on how to create an LPM in SELinux. So, here goes. Notice that this is for educational purposes only and would only take you so far. You need to study the implications of LPMs and how SELinux works before you can actually use them.


  1. You know what SELinux is.
  2. You know what types, attributes, macros etc are in SELinux.
  3. You have read about Loadable Policy Modules (LPMs) and want to use them.
  4. You don't know how to write and compile/use an LPM.


  1. Set SELinux to permissive. (Not enforcing. This isn't a complete tutorial!)
  2. Get setools package (possibly from yum)
  3. Install selinux-policy-devel package (possibly from yum)

Operations: (su whenever you need to)

  1. Create a directory. I'm assuming /home/user/lpm
  2. cd into the directory and create a sample policy. (See below for policy where it will be explained). Let's call it myapp.te
  3. Copy the LPM makefile from /usr/share/selinux/devel. (This comes with selinux-policy-devel)
  4. Run "make"  < compiles the .te file
  5. Run "semodule -i myapp.pp"< loads the LPM
  6. Run "cp /usr/bin/tail ./tt2" < copies the tail script here for testing purposes
  7. Run "touch myapplog.log" < create a dummy log file
  8. Run "chcon -t myapp_exec_t tt2" < Assign label to executable (see policy for description)
  9. Run "chcon -t myapp_log_t myapplog.log"  < Assign label to log file
  10. Run "seaudit". Open log file "/var/log/messages" if you do not have auditd installed or "/var/log/audit/audit.log" if you do.
  11. Run "./tt2 myapplog.log" < Run the file.
  12. Take a look at the seaudit for auditting details. (See attached screenshots for details)
  13. Notice the denies. (tail requires many allows which we haven't put in the LPM. You can continue to fix these to get rid of all the denies.)

The policy:

-----------------------|      myapp.te       |---------------------


# Adopted from /usr/share/selinux/devel/example.te

# Declarations

type fs_t;
type unconfined_devpts_t;

type myapp_t;
type myapp_exec_t;
# myapp_t is a process (belongs to domain attribute)

domain_entry_file(myapp_t, myapp_exec_t)
# allow myapp_t to be transitioned to using myapp_exec_t

type myapp_log_t;

type myapp_tmp_t;

domain_auto_trans(domain, myapp_exec_t, myapp_t)
# transition from 'domain' (any process) to myapp_t through myapp_exec_t executable

# Myapp local policy
allow myapp_exec_t fs_t:filesystem associate;

allow myapp_t unconfined_devpts_t : chr_file *;
# allow myapp_t access to the terminal

allow domain myapp_exec_t : file {execute read write} ;
# allow any process to run myapp_exec_t

auditallow myapp_t myapp_log_t:file ra_file_perms;
auditallow myapp_t myapp_log_t:file read;
# auditallow myapp_t to read myapp_log_t

allow myapp_t myapp_tmp_t:file manage_file_perms;


1. SETroubleshoot showing error message (denied access to terminal) [[see here](http://i11.photobucket.com/albums/a181/recluzepb/seaudit1.png)]
2. SEAudit showing log with denies and grants [[see here](http://i11.photobucket.com/albums/a181/recluzepb/seaudit2.png)]


If you want to generate allow rules automatically, use audit2allow:

audit2allow -i /var/log/audit/audit.log

This will show you the rules which need to be added to the .te file for the whole thing to work.