\documentclass{article}
\usepackage{ols,epsfig}
\usepackage{url}
\begin{document}

%don't want date printed
\date{}

\title{\Large \bf SE Linux Tutorial for Linux Kongress}

\author{
Russell Coker \url=<russell@coker.com.au>=,\\
{\normalsize \url=http://www.coker.com.au/=} \\
} % end author

\maketitle

% You have to do this to suppress page numbers.  Don't ask.
\thispagestyle{empty}

\section{Introduction}

The aim of this tutorial is an advanced hands-on training in administering
NSA Security Enhanced Linux~\cite{ols2001:loscocco-smalley}.  The Debian
distribution is used because it's support for SE Linux is better than any
other distribution, and because I did most of the Debian development work
regarding SE Linux and know it well.  Most of the material covered here should
apply to other distributions when they have support for SE Linux.

To install a package on a Debian system the command \emph{dpkg -i package.deb}
is used.

At the start of this tutorial you will have a workstation with a root password
of "1234" and a set of Debian packages in the \emph{/root/pkg} directory that
can be installed.  Also in the \emph{/usr/src} directory there will be a
complete archive of kernel source.

\section{Kernel Build}

The first stage of installing SE Linux is to build a kernel with support for
it.  This involves firstly applying the \emph{LSM} kernel patch from
\url=http://lsm.immunix.org/= which includes the SE Linux patch.  For Debian
this patch is in the \emph{kernel-patch-2.4-lsm} and
\emph{kernel-patch-2.5-lsm} packages for the 2.4.x and 2.5.x kernels
respectively.

Install the package \emph{kernel-patch-2.4-lsm}.

In the /usr/src directory you will find the file \emph{linux-2.4.19.tar.bz2}.
Extract it with the command \emph{tar xvjf linux-2.4.19.tar.bz2}.  Now
change to the \emph{linux-2.4.19} directory that has been created and apply the
kernel patch with the command \emph{/usr/src/kernel-patches/all/apply/lsm}.

After the patch is applied run the command \emph{make menuconfig} to
configure the kernel.  There is a new section \emph{Security options} which
contains the options for SE Linux and other security options.  For SE Linux
turn on the options for \emph{Capabilities Support} (which SE Linux requires),
\emph{NSA SELinux Support}, and \emph{NSA SELinux Development Module}.

If a kernel is compiled with Development support then it boots into
\emph{permissive mode} by default, which means that it writes log messages
instead of preventing operations.  This is essential when you first setup
SE Linux, otherwise a mistake in the policy could render the machine
unbootable.

We will not compile the kernel now due to lack of time.


\section{First Stage of Installation (kernel and policy)}

The first stage of installing SE Linux is to install the \emph{login} program
from the package \emph{login\_20000902-12.se1\_i386.deb} which is needed to
assign the correct security context to the user when they login.

After this is installed then install the kernel image from
\emph{kernel-image-2.4.19lsm\_1\_i386.deb}.  But DO NOT REBOOT!

It is important not to reboot until all the other files are ready for SE
operation to avoid the problems of a partially working SE setup.

The next packages to install are the \emph{selinux} package that has the core
SE Linux administrative programs, and the \emph{selinux-policy-default} package
which has sample security policy files.  These are in
\emph{selinux\_2002070313-9\_i386.deb} and
\emph{selinux-policy-default\_2002070313-9\_all.deb} respectively, and must be
installed in this order.

The \emph{selinux-policy-default} package will ask you a number of questions
about policy files to remove.  Your workstation has a fairly minimal
configuration at the moment, so you can remove any policy files that don't
interest you (apart from \emph{named.te} and \emph{irc.te} which we need
for later exercises), later in the tutorial you may install other packages
so you may want to leave the policy files in place for such packages).  Also
please note that the \emph{sendmail.te} policy conflicts with that for other
mail servers so it must be removed.

If you accidentally remove a \emph{.te} file that you need, then later you can
copy it to \emph{/etc/selinux/domains/program/} from
\emph{/usr/share/selinux/policy/default/domains/program/} and run
"\emph{make -C /etc/selinux load}".

After you have finished deciding which policy files to remove the package
will then compile and install the policy.  Then it will label every file on
the file system with a security \emph{type}.  The core of SE Linux is
\emph{Domain Type} access control (known as \emph{DT}).  DT relies on every
object (file, directory, network port, etc) having a security type associated
with it, and every process being in a security \emph{domain}.  So the labelling
of all the files on the file system is a very important part of the
installation!

The final package to install in this phase is dpkg (the Debian packge manager).
The package contains a modified version of dpkg that will label files with
the correct SE Linux \emph{type} after installing them.

Now reboot the machine to use the new kernel.

\section{Second Stage of Installation}

In the previous section you installed the bare minimum SE Linux functionality,
the SE kernel support and a policy for the kernel to load.  The policy package
relabelled all files on the file system with correct types for you.  You also
installed a login program to allow you to login with the correct context, and a
modified version of \emph{dpkg} to allow you to install programs in the
correct context.

Now login to the machine, after entering your root password you will see the
following: \\


\begin{verbatim}
lyta login: root
Password:
Last login: Fri Aug 16 03:38:02 2002 on vc/2
Linux server 2.4.19lsm #1 Tue Aug 6 14:53:07 CEST 2002 i686 unknown unknown GNU/Linux

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.

Your default security context is root:user_r:user_t
Do you want to enter a new security context?[n]
\end{verbatim}

Now this means that it will log you in with the \emph{context} of
\emph{root:user\_r:user\_t} by default.

The security context is comprised of three parts, the first part is the
\emph{identity} which is the Unix username that you used to login.  The next
part is the \emph{role} which is one of the roles that are assigned to the
identity (an identity can have one role or multiple roles), role names
customarily end in \emph{\_r}.  The final part of the security context is the
\emph{domain}.  The domain name ends in \emph{\_t}, it is the determining factor
for all SE Linux security decisions.  Each role is limited to a certain set
of domains.

Therefore your \emph{identity} (your Unix username) limits your choice of
\emph{role}, which determines which \emph{domain} you can use, and therefore
what access you get to the system.

Now the security context of \emph{root:user\_r:user\_t} is not what you want,
you want to be able to continue doing administration work and configuring all
aspects of the system, the \emph{user\_t} domain is very limited.  This means
that you need to type "y" at the prompt to enter a new security context,
giving the following result:


\begin{verbatim}
Your default security context is root:user_r:user_t
Do you want to enter a new security context?[n] y

        Enter role  (return for default) [user_r]
\end{verbatim}

At this time you must type "sysadm\_r" to select the system administration
domain giving the following:

\begin{verbatim}
Do you want to enter a new security context?[n] y

        Enter role  (return for default) [user_r] sysadm_r
        Enter type  (return for default) [sysadm_t]
\end{verbatim}

Now you have to press ENTER to select the default domain of \emph{sysadm\t}
and you get a root shell with full administrative privileges.

However there is a problem!  At the time we labelled the files on the file
system the machine was running without SE Linux, so any files created after
the file system was labelled but before we booted a SE kernel will not have
a type associated with them (that means any files created during the
shut-down process).  To fix this we have to run "make -C /etc/selinux relabel".

Now you want put SE Linux in enforcing mode.  The program \emph{avc\_toggle}
is used to switch between \emph{permissive} mode (where messages are logged
and nothing else happens), and \emph{enforcing} mode (where actions prohibited
by policy are denied.  Run \emph{avc\_toggle} now to put the machine in
enforcing mode, and notice that it informs you of the new state by printing
\emph{enforcing} on the command line.  Also a message such as the following
will be logged by the kernel and appear on your screen:

avc:  granted  { avc\_toggle } for  pid=16153 exe=/usr/bin/avc\_toggle scontext=root:sysadm\_r:sysadm\_t tcontext=system\_u:system\_r:kernel\_t tclass=system


Now go to another virtual console and login as \emph{root} with the default
security context of \emph{root:user\_r:user\_t}.

Notice that in the session where you are logged in with the \emph{sysadm\_t}
domain you can run "\emph{ls -l ~root}", \emph{dmesg}, and "\emph{ps aux}" and
get the results that you are used to.  Now compare the results of the same
commands in the session that is logged in with the \emph{user\_t} domain.

When logged in as a non-administrative domain the \emph{ps} command will only
show you processes in the same domain and in certain other domains that you
have access to.  You can not see daemon processes, so if the system is running
a daemon that has a security hole a hostile user will be less able to discover
it's existence or know how to attack it.  Also the root home directory is
configured such that non-administrative users can not write to it (otherwise
they could replace the \emph{.bashrc} with a script that does something
nasty).  Finally \emph{dmesg} is denied from most users so that they can't
see details of system hardware, and when their actions are blocked by the
security policy they can't see why.

Now you have verified that SE Linux is working, try running \emph{avc\_toggle}
again and notice that the machine has re-entered \emph{permissive} mode, this
means that the login with the \emph{user\_t} domain can see all processes with
\emph{ps}, run \emph{dmesg}, etc.  After verifying this run \emph{avc\_toggle}
once more to leave the machine in \emph{enforcing} mode.

At any time if you need to know the mode the machine is in you can run the
program \emph{avc\_enforcing}, and it will tell you.  Try it now.

The next time you boot the machine you want it to run in enforcing mode, to
do this run the command "\emph{ln -s /sbin/avc\_toggle /etc/rc.boot}" to make
\emph{avc\_toggle} be run at boot time.

For the purposes of rest of the tutorial make sure you leave the machine in
enforcing mode.

\section{Installing Utility Programs}

Now you have a machine that has every process running in a security
\emph{domain} and every file and directory has a \emph{type} associated with
it.  But you are unable to determine what the domains and types are!

To do this you need to install some new packages, however the regular
\emph{dpkg} command will not work when SE Linux is in enforcing mode.  There is
a wrapper called \emph{se\_dpkg} which sets the correct security context that
you can use instead.  These are \emph{shellutils} for a modified version of
\emph{id} and adds the \emph{runas} command, \emph{procps} for a modified
\emph{ps}, and \emph{fileutils} adds the \emph{chcon} command and has modified
versions of \emph{cp}, \emph{mv}, \emph{install}, \emph{ls}, \emph{mkdir},
\emph{mkfifo}, and \emph{mknod}.

Install the packages \emph{shellutils\_2.0.12-2.se1\_i386.deb},
\emph{procps\_2.0.7-10.se1\_i386.deb}, and
\emph{fileutils\_4.1.10-2.se1\_i386.deb} now by using the \emph{se\_dpkg}
command.  This command will prompt you for the password matching the
\emph{identity} that you are using (in this case the root password).

Run the command \emph{id} from both of your root login sessions, notice how
it reports the different security context used for the processes in each
session.

Run the command "\emph{ls --context /}" and observe the different types being
used for the files.

Run the command "\emph{ps ax --context}" from the \emph{sysadm\_t} login and
observe the different security contexts being used for the daemons.

Run the command "\emph{ls --context `tty`}" from both sessions and observe
that the tty devices have a different type for each login.  This prevents
unauthorised access to a tty.  To test this use the \emph{wall} command, note
that when you run \emph{wall} as \emph{sysadm\_t} all users see it, but when
you run it as \emph{user\_t} only other users in \emph{user\_t} see it.

Now login as \emph{user\_r} on another console and run \emph{irc} to connect
to the IRC server.  Go to the other console and run "\emph{ps ax --context}"
and note how the IRC program runs in the \emph{user\_irc\_t} domain, now run
"\emph{ls -atr --context}" to see how the file that the IRC client creates
has a different context.  This is so that the IRC client has no access to
files or directories under your home directory, it can create and modify it's
own configuration files and nothing else.  Then if someone cracks the IRC
client it can't kill any programs you run, or read or modify any files you
own (apart from it's own configuration).  After writing this policy I spent
some time in IRC as \emph{root} and had some amusing discussions with IRC
users who seemed to think it was a security risk and could not be convinced
otherwise.

Now join the \#se channel, we will use that for distributing policy samples,
and for some discussion during the tutorial.  Also if you wish to discuss in
German with your friends please join the \#de channel as well (unfortunately I
can't read German so I won't be on that channel).

\section{Installing Modified System Programs}

Now that you have installed the utility programs you next have to install
modified versions of some system programs.  Two important programs are
\emph{cron} and \emph{logrotate}.

We need a modified version of \emph{cron} to run the user cron jobs in the
correct context, and it has to check the \emph{type} of the crontab file to
ensure that it hasn't been created by someone who is not authorised for that
cron domain.

We need a modified \emph{logrotate} so that when it creates a new log file it
gives it the same \emph{type} as the old file that has been renamed.

Install the packages \emph{cron\_3.0pl1-72.se3\_i386.deb} and
\emph{logrotate\_3.5.9-10.se1\_i386.deb} now.


\section{Creating User Accounts}

On a SE Linux machine you may want to have users with a UID=0 (root users) who
are not permitted to use the \emph{sysadm\_r} for administrative access.  To
keep them out they have to be prevented from accessing \emph{/etc/shadow},
otherwise they could run crack on the passwords.

This of course requires a mechanism for changing the password.  There are
wrappers for the programs \emph{passwd}, \emph{chsh}, \emph{chfn}, \emph{vipw}, 
and \emph{useradd}, these are \emph{spasswd}, \emph{schsh}, \emph{schfn},
\emph{svipw}, and \emph{suseradd} respectively.  The main wrapper programs
\emph{spasswd}, \emph{schsh}, and \emph{schfn} do not allow specifying any
parameters (so you can't change the password, shell, or finger details for
anyone else's account).  The \emph{svipw}, and \emph{suseradd} wrappers allow
specifying parameters but can only be run by the administrator in domain
\emph{sysadm\_t}.  If you are logged in as root with administrative
privileges then you can change someone else's password with \emph{sadminpaswd}.

Now change the root password with \emph{spasswd}, create a new user for your
own use with \emph{suseradd}, and edit the user's details with \emph{svipw}.

After adding the new user you need to assign them to a role (or roles).  To
do this firstly edit the file \emph{/etc/selinux/users}.  If you have an
account named \emph{john} that you want to allow for the \emph{user\_r} role
then you add "\emph{user john roles user\_r;}" to the file.  If you want to
grant access to the role \emph{sysadm\_r} as well then add
"\emph{user john roles \{ user\_r sysadm\_r \};}".  After saving the changes
apply them with the command "\emph{make -C /etc/selinux load}".  Note that
the default role is \emph{user\_r}, if a user is not permitted any other role
then there is no need to specifically add them to the policy.  However adding
the user to the policy allows syslog messages about denied actions to include
the user name (which makes it easier to determine which user is doing things
you don't like), so it's handy to have.

After adding an entry for a user in the \emph{users} file you must set them
a default security context for their login sessions, this is determined by
the file \emph{/etc/security/default\_context}.  In the case of an account
\emph{john} you would add \emph{john:user\_r:user\_t} to the
\emph{/etc/security/default\_context} file.

The next thing to do is to relabel their home directory to the correct type
through the following commands:
\begin{verbatim}
find /home/john | xargs chcon -h system\_u:object\_r:user\_home\_t
chcon -h system\_u:object\_r:user\_home\_dir\_t /home/john
\end{verbatim}

Now install \emph{ssh} from \emph{ssh\_3.4p1-2.se1\_i386.deb}, create a new
account named \emph{test} that is only authorised for the \emph{user\_r}
domain and tell the people on the computer next to yours the password and
the IP address of your machine so that they can login.

Now login to each other's machines and have a look around.  Try various
methods of tracing what the other person is doing on your machine as
\emph{sysadm\_t} while they (as \emph{user\_t}) can't see what you are
deoing.  Please play nice when logging into each other's machines (just in
case they made a mistake).

\section{Starting and Stopping Daemons}

When a daemon is run it has to be run in the correct context to ensure that it
gets access to the resources it needs, and that it is denied access to
everything it shouldn't be accessing.

The daemon start scripts are run in the context
\emph{system\_u:system\_r:initrc\_t}, and there are policy rules to cause a
transition from the \emph{initrc\_t} domain to the domain the daemon runs in.
Inspect the file \emph{/etc/selinux/domains/program/named.te} and notice that
it has \emph{daemon\_domain(named)} on line 14.  The \emph{daemon\_domain}
macro is defined on line 932 of \emph{/etc/selinux/macros/global\_macros.te}
which calls the macro \emph{daemon\_base\_domain} on line 901 of the same file.
The relevant line is line 907 which calls the \emph{domain\_auto\_trans} macro
to setup an automatic domain transition.  When the \emph{initrc\_t} domain
executes a file of type \emph{named\_exec\_t} it will be run in the new domain
\emph{named\_t}.

For more information on SE Linux policy see Stephen D.\ Smalley's
paper~\cite{smalley}.

When logged in under the \emph{sysadm\_t} domain you can stop a daemon in the
usual fashion.  To start a daemon you need to use the \emph{run\_init} program
to start it in the correct context, \emph{run\_init} will run a specified
program in the \emph{system\_u:system\_r:initrc\_t} context.  Stop the
\emph{named} daemon now with the command "\emph{/etc/init.d/bind stop}", and
restart it with the command "\emph{run\_init /etc/init.d/bind start}".

Now use the command "\emph{ps ax --context | grep named}" to verify that it is
running and in the correct domain.

\section{Adding a New User Domain}

To add a new user domain \emph{second\_t} and role \emph{second\_r}
edit the file \emph{/etc/selinux/domains/user.te} add the following:
\begin{verbatim}
full_user_role(second)
allow system_r second_r;
allow sysadm_r second_r;
\end{verbatim}
The first line creates the domain \emph{second\_t}, and the types
\emph{second\_home\_dir\_t} and \emph{second\_home\_t} (for the home directory
and for files under the home directory respectively),
\emph{second\_tmp\_t} for files created under /tmp,
\emph{second\_tmpfs\_t} for shared memory created in the context of tmpfs, and
\emph{second\_tty\_device\_t} and \emph{second\_devpts\_t} for user labelling
of tty devices and pseudo-tty devices respectively.  It also creates all the
basic policy rules for using these types.

The reason for having the types \emph{second\_home\_dir\_t} and
\emph{second\_home\_t} is so that the IRC client can be given access to ~user
which is of type \emph{second\_home\_dir\_t} but not to ~user/Mail which is of
type \emph{second\_home\_t}.

SE Linux does not internally support any type of object orientation,
inheritance of domains/types, etc.  Also there is currently no policy language
that supports such features (one could be written, but no-one has done so yet).
So to get the features we need for easily creating new domains etc we use
\emph{M4} macros.

Now create a new user for use in this domain with the \emph{suseradd} program,
add them to the \emph{/etc/selinux/users} file with an entry that gives them
access to the role \emph{second\_r} (and no other roles), then run
"\emph{make -C /etc/selinux load}" to apply the new policy.  Then run the
following commands to apply the correct labels to the home directory:
\begin{verbatim}
find /home/user | xargs chcon -h system_u:object_r:second_home_t
chcon -h system_u:object_r:second_home_dir_t /home/user
\end{verbatim}

The next thing to do is set the default domain for the new role, to do this
edit the file \emph{/etc/security/default\_type} and add the line
"\emph{second\_r:second\_t}".  This is for the login prompt for the domain.

Now try logging in as the new user!

\section{Setting up a Chroot Environment}

Now we want to setup a chroot environment running the old Debian version
named \emph{Potato} from the \emph{user\_t} domain.

The administrator of the chroot environment can allow other people to
login as root with administrative privileges (they can add accounts, change
passwords etc), but they can't escape from the chroot.  Also some of the files
in the chroot environment can be set as read-only, so that the administrative
user inside the chroot can't change then.  This is both a protection against
having the chroot environment "\emph{cracked}", and a way of limiting what
the root user inside the chroot can do.

Firstly add the line "\emph{chroot(user, potato)}" to
\emph{/etc/selinux/domains/user.te}.  Then create the file \\
\emph{/etc/selinux/domains/misc/custom.te} with the line
"\emph{file\_type\_auto\_trans(user\_t, src\_t, potato\_ro\_t)}".  Now load the
policy.

Now login as \emph{root} in the \emph{user\_r} role and extract the archive
\emph{/usr/src/potato.tar.bz2} with the command
"\emph{cd /usr/src ; tar xvjf potato.tar.bz2}".  This archive includes the
script \emph{mountit} as follows:
\begin{verbatim}
#!/bin/bash -e

if [ "$1" == "mount" ]; then
  cd $2
  mount -n none -t proc proc
  mount -n /dev dev --bind
fi
if [ "$1" == "umount" ]; then
  cd $2
  umount -n `pwd`/proc/
  umount -n `pwd`/dev
fi
\end{verbatim}

Also the script \emph{setperms} as follows:
\begin{verbatim}
#!/bin/bash -e

# the first parameter is the full path to the root directory
# the second parameter is the name of the chroot (the second parameter to
# the chroot() macro

echo cd $1
IDENTITY=`id -c | cut -f1 -d:`
BASECON=$IDENTITY:object_r:$2
find home root tmp var | xargs -l300 chcon ${BASECON}_rw_t
find etc/init.d | xargs -l300 chcon ${BASECON}_dropdown_t etc/init.d
chcon ${BASECON}_ro_t var var/lib
find /var/lib/dpkg | xargs -l300 chcon ${BASECON}_ro_t
chcon ${BASECON}_super_entry_t entry
\end{verbatim}

The files in the chroot are currently labelled as \emph{potato\_ro\_t} due to
the "\emph{file\_type\_auto\_trans(user\_t, src\_t, potato\_ro\_t)}" which
causes any files or directories created under a \emph{src\_t} directory by
the \emph{user\_t} domain to be labelled as \emph{potato\_ro\_t}.

So the before we try running anything we have to use the \emph{setperms}
script to label some of the files and directories as allowing writes, the
command is "\emph{/usr/src/potato/setperms /usr/src/potato potato}".

Now to get the chroot going you first have to mount \emph{/proc} and
\emph{/mount} under the chroot with the \emph{mountit} script, the command
"\emph{/usr/src/potato/mountit mount /usr/src/potato}" will do this.

Before you try logging in to the chroot environment you have to change the
root password, the command "\emph{cd /usr/src/potato ; chroot . passwd}" will
do this.

Now we have the files setup for a chroot environment and a password in place,
all we have to do is allow logins to it by starting a syslogd daemon and a ssh
daemon.  I have configured the ssh daemon to run on port 222 (so it doesn't
conflict with the main sshd), so all you have to do is run
"\emph{cd /usr/src/potato ; chroot . /etc/init.d/sysklogd start}" to start the
system log, and
"\emph{cd /usr/src/potato ; chroot . /etc/init.d/ssh start}" to start sshd.

\begin{thebibliography}{99}

\bibitem{ols2001:loscocco-smalley}\emph{Meeting Critical Security Objectives with Security-Enhanced Linux} \\
Peter A.\ Loscocco, NSA, loscocco@tycho.nsa.gov \\
Stephen D.\ Smalley, NAI Labs, ssmalley@nai.com \\
{\tt \small \url=http://www.nsa.gov/selinux/ottawa01-abs.html/=}

\bibitem{smalley}\emph{Configuring the SELinux Policy} \\
Stephen D.\ Smalley, NAI Labs, ssmalley@nai.com \\
{\tt \small \url=http://www.nsa.gov/selinux/policy2-abs.html/=}

\end{thebibliography}

\end{document}


