SE Linux - Security Enhanced Linux for kernel 2.6.6

(Written: Oct 23, 2004)

This page documents how I installed SE Linux on my Debian/Testing with a custom 2.6.6 kernel. It shall help other people trying the same.

Index

Introduction

SE Linux is a set of tools and kernel patches (Kernels since 2.6.0-test3 (?) already include SE Linux support by NSA, it only needs to be enabled) that implement a mandatory access control. In short, it gives you much more flexible access control than the default unix access control system, you can specifiy much more exactly what a process or user can or cannot do. The default policy is quite restrictive. According to some people it's well suitable for internet servers running few specialized services that need enhanced security while it's perhaps to restrictive for a normal desktop user and the policy is to complicated to manage for large application servers. But some people might have a different opinion and you'd best ask a specialist. See SELinux FAQ for more.

$POLICY
The directory that contains source files of the policy you want to use (above all Makefile and users). For me $POLICY=/etc/selinux/src (see below problems with src/) but as far as I understand it should be /etc/selinux for Debian and /etc/security/selinux/src/policy for other distributions. make, make relabel, checkconfig etc. must by run in $POLICY because there are the files needed and the Makefile.

Overview

What a user can or cannot do is determined by his unix security id (uid, gid) and SE Linux security context and the policy. Security context has the form identity:role:domain - domain is a subset of so called types. Identity is username or a default id (user_u, system_u etc.) if no usernames are specified in the file $POLICY/users and compiled into the policy. Both security models - unix and SE Linux - work at parallel (if set so) thus the user must satisfy both of them. To be able to do root stuff you must both become root with su - root that will preserve your security context (most probably aUserName:user_r:user_t) and gain the sysadm_r with newrole -r sysadm_r. Of course you must be allowed to gain that role in $POLICY/users. Note: domain is a type of the process being run (bash, su...) thus it changes quite often as opposed to role.

The 'access rights' are determined by the policy, which can only be changed by an administrator (the role sysadm_r), and si applied to the filesystem (FS) by make relabel or to a part of the FS by setfiles. If you want to change it you need to edit some files in $POLICY (?), e.g. 'users' to change roles available to particular users and then you've to recompile and reload the policy. Thus, as opposed to some other security models, ordinary users cannot change 'access rights' of their own files.

$POLICY/users determines what roles are available to what user. The user 'kuba' cannot gain any other role than those allowed for him, even if he su - root he won't be able to gain sysadm_r unless $POLICY/users contains the line 'user kuba roles { user_r sysadm_r };'. That's because his uid changed to 0, but SE Linux still remebers that he is kuba and not root. There shall be a sample file in $POLICY.

/etc/selinux/contexts/default_contexts determines the default context set after such operations such as a user login and ssh user login. The default contexts says which of his available roles shall a user gain after the action. If there is 'user kuba roles { user_r staff_r sysadm_r };' in $POLICY/users (which is normal for those who shall have access to root rights) we can set whether he shall become kuba:user_r:user_t or kuba:staff_r:staff_t or kuba:sysadm_r:sysadm_r when he logs in. The default_contexts can be changed without the need to recompile the policy. You can set your prefered roles (only those available to you) in $HOME/.default_contexts.

/etc/selinux/contexts/default_type determines default types for the given roles, it's used by newrole when you specify a role but not a type (e.g. newrole -r sysadm_r instead of newrole -r sysadm_r -t sysadm_t).

Setup SE Linux for Debian/testing (based on Lemuria's guide)

Not all information in the guide applied to my system - libselinux have already been installed and I had a lot of troubles with selinux-policy-default.

  1. Configure kernel to be compiled with SE Linux support.

    I assume you know how to compile a kernel for Debian. See the guide, Debian Kernel HOWTO etc.

    aUser:/usr/src/linux$ make menuconfig

    General setup-> 
     [*] Auditing support     # Needed for SE Linux logging
      [*]  Enable system-call auditing support
    Security->Security options-> 
     [*] Enable different security models 
     <M> Default Linux Capabilities
     [*] NSA SELinux Support
     [*] NSA SELinux Development Support # kernel will start in permissive mode by default
    File systems->
     [*] Ext3 Security Labels       # Enable additional security info for files
     <*> ROM file system support    # fomfs
     Pseudo filesystem->
      [*] /dev file system support (OBSOLETE)
        
  2. Get the packages you need
    1. Add unstable into your sources.list and set it's priority to be the lowest => you can install the needed packages that are not in testing (selinux-default-policy) and none of existing pacakges from testing will be replaced by unstable (this works with apt-get, not with dselect that ignores /etc/apt/preferences):

      /etc/apt/preferences:

         # Set Never-replace-existing package priority for unstable packages => prevent upgrading to testing
         Package: *
            Pin: release a=unstable
            Pin-Priority: 50
         # Set Always-install priority to SELinux packages
         # l = label, see http://selinux.lemuria.org/newselinux/Release
         Package: *
            Pin: release l=etbe
            Pin-Priority: 1100

      /etc/apt/sources.list:

         # SE Linux patches etc.
         # For sid and sarge, use Russel Cokers new packages:
         deb http://selinux.lemuria.org/newselinux ./     # make sure $http_proxy is set, if needed
         # Unstable: selinux-default-policy is not in testing
         deb ftp://ftp.cz.debian.org/debian unstable main contrib non-free
              
    2. root# apt-get update
      root# apt-get install checkpolicy expect policycoreutils selinux-doc selinux-utils selinux-policy-default
      root# apt-get dist-upgrade
      # this shall upgrade to SE Linux pacakges as coreutils

      Check that packages at deb http://selinux.lemuria.org/newselinux have replaced (possibly downgraded) the original ones.
      You may get some errors while installing selinux-policy-default and its installation may fail, ignore it for now.
      You may also install the package setools with various utilities.

  3. Compile & install the kernel
    • aUser:/usr/src/linux$ make-kpkg clean
    • aUser:/usr/src/linux$ fakeroot make-kpkg --initrd --revision=3.selinux1 --append-to-version -selin kernel_image modules_image #the --initrd is very important; you can set your own revision and append-to-version.
    • root:/usr/src# dpkg -i *-2.6.6-selin*3.selinux1*.deb
    • /etc/lilo.conf - add something like (perhaps you can also set this kernel as the default one):
         image=/boot/vmlinuz-2.6.6-selin # SE Linux
            label=Deb3-SElin             # Any label you want to see in the lilo's menu
            root=/dev/hda1               # The partition where the root / is (here: the 1st primary partition)
            read-only
            initrd=/boot/initrd.img-2.6.6-selin
            #addappend="enforcing=1"     # uncomment when everything is ok otherwise the 'permissive' mode is used
    • root# lilo
  4. System configuration: mkdir /selinux (a virtual filesystem for SE Linux) if it doesn't already exist and add something like
       none /selinux selinuxfs defaults 0 0

    to your /etc/fstab to mount it on boot.

  5. Package selinux-policy-default troubleshooting

    You may get some errors while installing selinux-policy-default and its installation may fail. Anyway the files shall be installed - see /etc/selinux/ (Note: RedHat uses /etc/security/selinux/).
    The errors you can see:

    Problems with src/: run-parts fails because of /usr/share/selinux/policy/current or /etc/selinux/src
    The packages creates a symlink /etc/selinux/src to point to /usr/share/selinux/policy/current/ which doesn't exist (there's only default/).
    SOLUTION: cd /usr/share/selinux/policy/; cp -R default/ current; Copy it, do not create symlink, beacuse of future changes.
    Complains about a nonexistent file needed by another one
    Create a dummy file of the given name with touch. May be this is not needed when you follow the steps given below.

    If you've troubles with the package you can compile the policy by yourself as long as you've got a Makefile and others in $POLICY (see above if it points to a nonexistent directory)
    root:$POLICY# make clean; make; # this will install the unusable policy.18
    root:$POLICY# checkpolicy -c 17 -o policy.17; mv policy.17 /etc/selinux/policy/

    Now you shall have policy.17 that can be loaded at boot. Note: May be checkpolicy may report some errors when not run under the SE Linux kernel, I haven't tried.

  6. Make SE Linux aware of users - see $POLICY/users above. You should at least assign sysadm_r and staff_r to yourself, otherwise you want be able to do anything under SE Linux. So add the line 'user replace-by-your-username roles { user_r staff_r sysadm_r };' You should add the ordinary users too to see their usernames in SE Linux logs instead of 'user_u'. After modifying this file you must recompile & reload the policy: root:$POLICY# checkpolicy -c 17 -o /etc/selinux/policy/policy.17 (or root:$POLICY# make reload if you've changed the Makefile as mentioned below). The next time you'll add a new user you can use seuser from the setools package that will do it correctly.
  7. Relabel the filesystem - this will assign type, user etc. to all directories and files according to a policy. Go to the policy source directory and run: root:$POLICY# make relabel It will take a while. It must be done after adding users into $POLICY/users and recompiling the policy to label the home directories of the users with their real usernames instead of the generic user_u.
  8. Reboot [again] to the SE Linux - you should see no errors during the boot process and dmesg shall show messages as "SELinux: Initializing. SELinux: Starting in permissive mode" etc.
    Check that you context is correct and displays you username, not user_u: id.
    Check you can switch into the sysadm_r (assuming you've allowed it): newrole -r sysadm_r. This will require your user password. Even if you authenticate well, you can get the error: "your-username:sysadm_r:sysadm_t" is not a valid context - this means you're not allowed to get this role. Check $PROFILE/users and id. "Couldn't get default type" means either you mistyped the role name or there is no default type specified for it in /etc/selinux/contexts/default_type.
  9. Run the system and analyse security logs to learn what must be changed in the policy to let the system run without too much trouble. Typically there'll be a lot of 'permission denied' messages and you will perhaps need to relax the policy a bit to keep some applications working in the enforcing mode. E.g. Eclipse help won't work anymore with the default policy because it needs to start a server and lunch a browser for it. The GUI tool seaudit from the setools package may be a great help in this task. Notice that this is only possible if you enabled auditing support in the kernel (see above).
  10. Switch to the enforcing mode when you are sure that your policy and applications are ready for that. So far you've been in the permissive mode when SE Linux rules are ignored - they aren't enforced - and the only thing done is logging denials.
    To go to the enforcin mode run either root# enforcing 1 or root# echo 1 > /selinux/enforce. To set it permanently to the enforcing mode uncomment the last line in lilo.conf shown above.
"New SE Linux"
As far as I understand it, SE Linux has been reimplemented between 2.4 kernels (including Debian stable - Woody) and 2.6 kernels, into which it got merged. Thus if you use either testing(Sarge) or usntable (Sid) you must use the new SE Linux packages. The vital package selinux-policy-default is not available in testing because it depends upon a library that is in unstable. We will deal with that later.
policy.VERSION (e.g. policy.17)
The version of a policy is automaticaly assigned to it when the binary policy file is generated (see man checkpolicy) and it reflects the format of the file, thus you cannot change it. If you use unpatched 2.6.6 kernel as I do you cannot load a policy.18 because the kernel supports only formats 15-17. After reboot dmesg would show 'security: policydb version 18 does not match my version range 15-17' and perhaps load_policy would fail too with "Warning! Error while getting boolean names: Success".
SOLUTION: Create an older policy format. selinux-policy-default doesn't manage this, you must do it manualy. Go to $POLICY, which containes sources files for the policy. Run there make clean; make. This shall create policy.conf and policy.18 (that cannot be loaded as explained). Now, when you have policy.conf, you can compile a different version of the policy: checkpolicy -c 17 -o policy.17; mv policy.17 /etc/selinux/policy/ . Now the policy shall be loaded and ready to be loaded on boot.
To solve it permanently - edit $POLICY/Makefile and add 'POLICYCOMPAT = -c 17', 'CHECKPOLICY_OPTS = -c 17', then change calls to checkpolicy: $(CHECKPOLICY) -o $@ policy.conf becomes $(CHECKPOLICY) $(CHECKPOLICY_OPTS) -o $@ policy.conf. There shall be 2 such targets: $(POLICYVER) and $(LOADPATH).
Policy.18 shall be supported by the kernel 2.6.8.

Installed utilities

selinuxdisable
selinuxenabled tool to determine whether SE Linux is enabled (returns 0) or not (-256)
selinuxconfig prints SE Linux configuration info
id print's current user's context
ls --context show context for files in `pwd`
checkpolicy compile and install a policy
setenforce [0|1] toggle the enforcing/the permissive mode
newrole [-r|-t] run a shell with a new role
sestatus [-v] display info about SE Linux, root only
setfiles relabel a given part of the filesystem
...