Debian and Google Summer (Winter) Of Code

Debian is participating in the Google Summer Of Code (or Winter if you are in the southern hemisphere).

It would be good if we could get a SE Linux related project in. If you are interested in doing some SE Linux work (or other security related work) in this regard then please let me know. I’m interested in helping mentor for such projects.

SE Linux on /.

The book SE Linux by Example has been reviewed on Slashdot.

The issue of Perl scripts was raised for discussion. It is of course true that a domain which is permitted to run the Perl interpreter can perform arbitrary system calls – it can therefore do anything that SE Linux permits that domain to do. This is in fact a demonstration of how SE Linux does the right thing! If you want to restrict what can be done when executing the Perl interpreter then you can have a domain_auto_trans() rule to have Perl run in a different domain.
Restricting Perl (as used by one particular program) is actually easier than restricting a complex application run by users such as Firefox. Users want to use Firefox for web browsing, local HTML file browsing, saving files that are downloaded from the web, running plugins, and more. Granting Firefox access to perform all those tasks means that it is not restricted from doing anything that the user can do.

A claim was made that a novice users would not understand how to use SE Linux. The fact is that they don’t need to. I know many novice computer users who are running SE Linux systems, it just works! It’s more advanced users that have to learn about SE Linux because they configure their machines more heavily.

The essential difference between path-based access control and Inode based access control is that the standard Unix commands to control file access (chmod, chown, and chgrp) all operate on Inodes. If a file has 1000 hard links then I can restrict access to all of them via a single chmod or chcon (the SE Linux command that is comparable to chmod) command. AppArmor does things differently and implements an access control model that is vastly different to the Unix traditions. SE Linux extends the Unix traditions with Mandatory Access Control.

Granting different levels of access to a file based on the name of the link which is used is a horror not a feature.

I wrote this as a blog entry rather than a /. comment because my lack of Karma means that less people will read my /. comments than my blog.

creating a new SE Linux policy module

Creating a simple SE Linux policy module is not difficult.

audit(1173571340.836:12855): avc: denied { execute } for pid=5678 comm=”spf-policy.pl” name=”hostname” dev=hda ino=1234 scontext=root:system_r:postfix_master_t:s0 tcontext=system_u:object_r:hostname_exec_t:s0 tclass=file

For example I had a server with the above messages in the kernel message log from the spf-policy program (run from Postfix) trying to run the “hostnme” program. So I ran the following command to generate a .te file (SE Linux policy source):

dmesg|grep spf.policy|audit2allow -m local > local.te

The -m option to audit2allow instructs it to create a policy module. The local.te file is below:

module local 1.0;

require {
      class file execute;
      type hostname_exec_t;
      type postfix_master_t;
      role system_r;
};

allow postfix_master_t hostname_exec_t:file execute;

Then I used the following commands to create a policy module and package it:

checkmodule -M -m -o local.mod local.te
semodule_package -o local.pp -m local.mod

The result was the object file local.pp and in intermediate file local.mod (which incidentally can be removed once the build is finished).

After creating the module I used the following command to link it with the running policy and load it into the kernel:

semodule -i ./local.pp

execmod

Ulrich Drepper has written a good web page about text relocation which is most often noticed as execmod failures reported when running SE Linux. When an AVC message reports a failure of execmod against a shared object it means that the object has text relocations (the shared object code writes to code that it executes to fix up addresses). This is due to being compiled without -fPIC or -fpic.

The command eu-findtextrel (from the elfutils package) when run with a parameter of the shared object in question will tell you which functions were compiled without -fpic or -fPIC.

The module in question must be recompiled with -fpic or -fPIC to generate the correct code.

Without SE Linux it’s still a bug to compile a shared object without position independent code, so any shared object which can’t run under SE Linux because of execmod will probably have problems in other situations anyway (maybe only on certain architectures).

core files

The issue of core file management has come up for discussion again in the SE Linux list.

I believe that there are two essential security requirements for managing core files, one is that the complete security context of the crashing process is stored (to the greatest possible extent), and the other is that processes with different security contexts be prevented from discovering that a process dumped core (when attacking a daemon it would be helpful to know when you made one of it’s processes dump core).

The core file will have the same UID and GID as the process that crashed. It’s impossible to maintain the complete security context of the crashing process in this manner as Unix permissions support multiple supplementary groups and Unix filesystems only support one GID. So the supplementary groups are lost.

There is also a sysctl kernel.core_pattern which specifies the name of the core file. This supports a number of modifiers, EG the value “core.%p.%u.%g” would give a file named “core.PID.UID.GID“. It would be good to have a modification to the kernel code in question to allow the SE Linux context to be included in this (maybe %z).

To preserve the SE Linux context of the crashing process with current kernel code we need to have a unique type for each process that dumps core, this merely requires that each domain have an automatic transition rule for creating files in the directory chosen for core dumps. In the default configuration we have core files dumped in the current directory of the process. This may be /tmp or some other common location which allows an attacker to discover which process is dumping core (due to the directory being world readable) and in the case of SE Linux there may be multiple domains that are permitted to create files in /tmp with the same context which gets in the way of using such a common directory for core files.

The traditional Unix functionality is to have core files dumped in the current directory. Obviously we can’t break this by default. But for systems where security is desired I believe that the correct thing to do is to use a directory such as /var/core for core files, this can be easily achieved by creating the directory as mode 1733 (so that any user can create core files but no-one but the sys-admin can read them) and then setting the core_pattern sysctl to specify that all core files go in that directory. The next improvement is to have a poly-instantiated directory for /var/core such that each login user has their own version. That way the user in question could see the core files created by their own processes while system core files and core files for other users would be in different directories. Poly-instantation is easier to implement for core files than it is for /tmp (and the other directories for which it is desirable) because there is much less access to such a directory. When things operate correctly core files are not generated, and users never need to access each other’s core files directly (they are mode 0600 so this isn’t possible anyway).

This area will require a moderate amount of coding before it works in the ideal manner. I aim to briefly describe the issues only in this post.

more about vista security

While reading the discussion of Vista security on Bruce Schneier’s blog it occurred to me that comparing the issues of DRM that face MS with the issues faced by SE Linux developers provides some benefits.

SE Linux is designed to enable the owner of a computer to effectively enforce security policies to protect their system integrity and the confidentiality of their data. Some of the SE Linux users (military users) use all the available features, but most people only use the targeted policy which provides a sub-set of the system integrity and data confidentiality protections that are available to give a greater ease of use.

Fedora and Red Hat Enterprise Linux ship with the SE Linux targeted policy enabled by default. This policy is not something that most users notice. The main program that is commonly used which might have an issue with the default SE Linux policy is Apache. Fedora and RHEL systems that do not run Apache (which is most of them) can run SE Linux with almost no costs.

setsebool -P httpd_disable_trans 1
/etc/init.d/httpd restart

It seems clear to me that there is no good reason for disabling SE Linux by default. There are reasons for running a particular daemon in the unconfined_t domain via the FOO_disable_trans boolean. EG to run Apache without restrictions you would type the above commands.

In spite of the SE Linux targeted policy being so easy to use, the fact that it prevents certain daemon compromises from allowing immediate control of the system, and also prevents some kernel exploits from working, there are still some people who turn it off when installing Fedora and RHEL systems and advise others to do so.

Given this great fear of some people to use a technology that is specifically designed for their own benefit I find it difficult to imagine that any users will be inclined to accept the MS DRM technology that is specifically designed to go against their interests.

ESR claims that the 64bit transition is the critical period for Linux to move on the desktop. While he makes many interesting observations I don’t find his argument convincing. Firstly current P4 CPUs with PAE can handle significantly more than 4G of RAM (64G is possible now). Secondly it’s quite possible to run a 64bit kernel with 32bit applications, this means that you can use a 64bit kernel to access >64G of RAM with each 32bit application getting direct access to something slightly less than 4G of virtual memory. As ESR’s point seems based on total system memory the 4G per application doesn’t seem to be an issue. As an aside the only applications I’ve used which could benefit from >4G are database servers (in the broadest interpretation – consider an LDAP server as a database) and JVM environments. Again it would not be difficult to ship an OS with mostly 32bit code that has a 64bit kernel, JVM, and database servers.

I hope that Vista will be a good opportunity for mass transition to Linux. Vista offers little that users desire, many things that will hurt them, and is expensive too!

With Vista you pay more for the OS and more for the hardware (Vista has the usual excessive Windows hardware requirements plus the extra hardware for TPM encryption) without providing anything substantial in return.

What I want to see next is support for Security Enhanced X to protect desktop environments against hostile X clients. This will make a significant difference to the security of Linux desktop environments and provide another significant benefit for choosing Linux over Windows. While MS is spending their effort in making their OS act against the best interests of the users we will keep making Linux enforce the access controls that users need to protect their systems. Hopefully Linux users will choose to use SE-X, but if they don’t they are given the freedom to make that choice – unlike the poor sods who use Windows.

installing Debian Etch

A few days ago I installed Debian/Etch on my Thinkpad. One of the reasons for converting from Fedora to Debian is that I need to run Xen and Fedora doesn’t support non-PAE machines with Xen. Ironically it’s hardware supplied to me by Red Hat (Thinkpad T41p) that is lacks PAE support and forces me to switch to Debian. I thought about just buying a new dual-core 64bit laptop, but that seems a bit extravagant as my current machine works well for everything else.

Feeling adventurous I decided to use the graphical mode of the installer. I found it a little confusing, at each stage you can double-click on an item or click on the continue button to cause the action to be performed. The partitioning section was a little unclear too, but given that it has more features than any other partitioning system I’ve seen I wasn’t too worried (options of creating a degraded RAID array and for inserting a LUKS encryption layer at any level are really nice). The option to take a screen-shot at any time was also a handy feature (I haven’t yet inspected the PNG files to see what they look like).

Another nice feature was the way that the GUI restarts after a crash. While it was annoying that the GUI started crashing on me (and would have prevented a less experienced user from completing the install) the fact that it didn’t entirely abort meant that I could work around the problem.

I have not yet filed any bug reports against the installer because I have not done a repeatable install (there is a limit to how much testing I will do on my most important machine). In the next few days I plan to do a few tests of the graphical installer on test hardware for the operations that are important to me and file appropriate bug reports. I encourage others to do the same, the graphical mode of the installer and the new encryption and RAID features are significant improvements to Debian and we want them to work well.

I have realised that it won’t be possible to get SE Linux as good as I desire before the Etch release, even if the release is delayed again. I’m not sure how many fixes can go in after the release (I hope that we could move to a model similar to RHEL – but doubt that it will happen). So I now plan to maintain my own repository of Etch SE Linux packages and for other packages which need changes to make them work in the best possible manner with SE Linux. I will append something like “.se1” to the version of the packages in question, this means that they will be replaced if a security update is released for the official package. Apart from the SE Linux policy packages (for which any security updates will surely involve me) the changes I am going to make will not be major and will be of less importance than a security update.

I will also add other modified and new packages to my repository that increase the general security of Etch. Apart from SE Linux all the changes I intend to host will be minimal cost issues (IE they won’t break things or increase the difficulty of sys-admin tasks), and the SE Linux related changes will not break anything on non-SE systems. So someone who wants general security improvements without using SE Linux might still find my repository useful.

Debian SE Linux policy bug

checkmodule -m -o local.mod local.te
semodule_package -o local.pp -m local.mod
semodule -u local.pp

Save the following policy as local.te and then run the above commands to make semodule work correctly and to also allow restorecon to access the console on boot.

module local 1.0;

require {
        class chr_file { read write };
        class fd use;
        type restorecon_t;
        type tmpfs_t;
        type initrc_t;
        type semanage_t;
        role system_r;
};

allow restorecon_t tmpfs_t:chr_file { read write };
allow semanage_t initrc_t:fd use;
4

SE Linux on Debian in 5 minutes

Following from my 5 minute OSDC talk yesterday on 5 security improvements needed in Linux distributions I gave a 5 minute talk on installing SE Linux on Debian etch. To display the notes I formatted them such that they were in 24 line pages and used less at a virtual console to display them. The ultra-light laptop I was using has only 64M of RAM which isn’t enough for a modern X environment and I couldn’t be bothered getting something like Familiar going on it.

After base install you install the policy and the selinux-basics package:

# apt-get install selinux-basics selinux-policy-refpolicy-targeted
The following extra packages will be installed:
checkpolicy libsemanage1 mime-support policycoreutils python python-minimal
python-selinux python-semanage python-support python2.4 python2.4-minimal
selinux-utils
Suggested packages:
python-doc python-tk python-profiler python2.4-doc logcheck syslog-summary
The following NEW packages will be installed:
checkpolicy libsemanage1 mime-support policycoreutils python python-minimal
python-selinux python-semanage python-support python2.4 python2.4-minimal
selinux-basics selinux-policy-refpolicy-targeted selinux-utils
0 upgraded, 14 newly installed, 0 to remove and 0 not upgraded.
Need to get 6362kB of archives.
After unpacking 41.5MB of additional disk space will be used.
Do you want to continue [Y/n]?

The package install process also configures the policy for the machine. The next step is to label the filesystems, this took 26 seconds on my Celeron 500MHz laptop with 20,000 files on an old IDE disk. The time is in proportion to number of files, often bottlenecked on CPU. A more common install might have 5* as many files with a 5* faster CPU so 30 seconds is probably common for labelling. See the following:

# fixfiles relabel

Files in the /tmp directory may be labeled incorrectly, this command
can remove all files in /tmp.  If you choose to remove files from /tmp,
a reboot will be required after completion.

Do you wish to clean out the /tmp directory [N]? y
Cleaning out /tmp
/sbin/setfiles:  labeling files under /
matchpathcon_filespec_eval:  hash table stats: 14599 elements, 14245/65536 buckets used, longest chain length 2
/sbin/setfiles:  labeling files under /boot
matchpathcon_filespec_eval:  hash table stats: 19 elements, 19/65536 buckets used, longest chain length 1
/sbin/setfiles:  Done.

The next step is to edit /boot/grub/menu.list to enable SE Linux, auditing, and put it in enforcing mode:

title   Debian GNU/Linux, kernel 2.6.17-2-686
root    (hd0,1)
kernel  /vmlinuz-2.6.17-2-686 root=/dev/x selinux=1 audit=1 ro enforcing=1
initrd  /initrd.img-2.6.17-2-686

Then reboot.

After rebooting view the context of your shell, note that the login shell will have a domain of unconfined_t when the targeted policy is used:

# id -Z
system_u:system_r:unconfined_t

Now let’s view all processes that are confined:

# ps axZ |grep -v unconfined_t|grep -v kernel_t|grep -v initrc_t
LABEL                             PID TTY   STAT   TIME COMMAND
system_u:system_r:init_t            1 ?     Ss     0:02 init [2]
system_u:system_r:udev_t         1999 ?     S.s    0:01 udevd --daemon
system_u:system_r:syslogd_t      3306 ?     Ss     0:00 /sbin/syslogd
system_u:system_r:klogd_t        3312 ?     Ss     0:00 /sbin/klogd -x
system_u:system_r:apmd_t         3372 ?     Ss     0:00 /usr/sbin/acpid -c /etc
system_u:system_r:gpm_t          3376 ?     Ss     0:00 /usr/sbin/gpm -m /dev/i
system_u:system_r:crond_t        3402 ?     Ss     0:00 /usr/sbin/cron
system_u:system_r:local_login_t  3423 tty1  Ss     0:00 /bin/login --
system_u:system_r:local_login_t  3424 tty2  Ss     0:00 /bin/login --
system_u:system_r:getty_t        3425 tty3  Ss+    0:00 /sbin/getty 38400 tty3
system_u:system_r:getty_t        3426 tty4  Ss+    0:00 /sbin/getty 38400 tty4
system_u:system_r:getty_t        3429 tty5  Ss+    0:00 /sbin/getty 38400 tty5
system_u:system_r:getty_t        3430 tty6  Ss+    0:00 /sbin/getty 38400 tty6
system_u:system_r:dhcpc_t        3672 ?     S.s    0:00 dhclient3 -pf /var/run/

The initial install of policy inserts modules to match installed software, if you install new software then you need to add new modules with the semodule command:

# semodule -i /usr/share/selinux/refpolicy-targeted/apache.pp
security:  3 users, 7 roles, 824 types, 67 bools
security:  58 classes, 11813 rules
audit(1165532434.664:21): policy loaded auid=4294967295
# semodule -i /usr/share/selinux/refpolicy-targeted/bind.pp
security:  3 users, 7 roles, 836 types, 68 bools
security:  58 classes, 12240 rules
audit(1165532467.874:22): policy loaded auid=4294967295

Note that the security and audit messages come from the kernel via printk, it is displayed on console login but you need to view the system log if logged in via ssh or running an xterm. Now you have to relabel the files that are related to the new policy:

# restorecon -R -v /etc /usr/sbin /var/run /var/log
restorecon reset /etc/bind context system_u:object_r:etc_t->system_u:object_r:named_zone_t
restorecon reset /etc/bind/named.conf context system_u:object_r:etc_t->system_u:object_r:named_conf_t
[...]
restorecon reset /etc/apache2 context system_u:object_r:etc_t->system_u:object_r:httpd_config_t
restorecon reset /etc/apache2/httpd.conf context system_u:object_r:etc_runtime_t->system_u:object_r:httpd_config_t
[...]
restorecon reset /usr/sbin/named context system_u:object_r:sbin_t->system_u:object_r:named_exec_t
restorecon reset /usr/sbin/apache2 context system_u:object_r:sbin_t->system_u:object_r:httpd_exec_t
restorecon reset /usr/sbin/rndc context system_u:object_r:sbin_t->system_u:object_r:ndc_exec_t
restorecon reset /usr/sbin/named-checkconf context system_u:object_r:sbin_t->system_u:object_r:named_checkconf_exec_t
[...]
restorecon reset /var/run/bind context system_u:object_r:var_run_t->system_u:object_r:named_var_run_t
restorecon reset /var/run/bind/run context system_u:object_r:var_run_t->system_u:object_r:named_var_run_t
restorecon reset /var/run/bind/run/named.pid context system_u:object_r:initrc_var_run_t->system_u:object_r:named_var_run_t
restorecon reset /var/run/motd context system_u:object_r:initrc_var_run_t->system_u:object_r:var_run_t
restorecon reset /var/run/apache2 context system_u:object_r:var_run_t->system_u:object_r:httpd_var_run_t
restorecon reset /var/run/apache2/cgisock.3558 context system_u:object_r:var_run_t->system_u:object_r:httpd_var_run_t
restorecon reset /var/run/apache2.pid context system_u:object_r:initrc_var_run_t->system_u:object_r:httpd_var_run_t
restorecon reset /var/log/apache2 context system_u:object_r:var_log_t->system_u:object_r:httpd_log_t
restorecon reset /var/log/apache2/error.log context system_u:object_r:var_log_t->system_u:object_r:httpd_log_t
restorecon reset /var/log/apache2/access.log context system_u:object_r:var_log_t->system_u:object_r:httpd_log_t

The -v option to restorecon causes it to give verbose output concerning it’s operations. Often you won’t do it in real use, but it’s good to illustrate the use.

Now you have to restart the daemons:

# killall -9 apache2
# /etc/init.d/apache2 start
Starting web server (apache2)....
# /etc/init.d/bind9 restart
Stopping domain name service...: bind.
Starting domain name service...: bind.

Apache and BIND now run in confined domains, see the following ps output:

system_u:system_r:httpd_t   3833 ?     Ss     0:00 /usr/sbin/apache2 -k start
system_u:system_r:httpd_t   3834 ?     S      0:00 /usr/sbin/apache2 -k start
system_u:system_r:httpd_t   3839 ?     Sl     0:00 /usr/sbin/apache2 -k start
system_u:system_r:httpd_t   3841 ?     Sl     0:00 /usr/sbin/apache2 -k start
system_u:system_r:named_t   3917 ?     Ssl    0:00 /usr/sbin/named -u bind

It’s not particularly difficult. I covered the actual install of SE Linux in about 1.5 minutes. I had considered just ending my talk there on a note of “it’s so easy I don’t need 5 minutes to talk about it” but decided that it was best to cover something that you need to do once it’s installed.

If you want to know more about SE Linux then ask on the mailing list (see http://www.nsa.gov/selinux for subscription details), or ask on #selinux on freenode.

The benefits of SE Linux

Today I discovered a bug in one of my programs, it called system() and didn’t correctly escape shell eta-characters. Fortunately I had written custom SE Linux policy for it which did domain_auto_trans(foo_t, shell_exec_t, very_restricted_t) so there was no possibility of damage.

The log files (which were not writable by the daemon by both SE Linux access control and Unix permissions) indicated that no-one had attempted to exploit the bug.