文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>SELinux from scratch

SELinux from scratch

时间:2007-04-26  来源:zhangzijian

原文:http://www-128.ibm.com/developerworks/linux/library/l-selinux.html  

SELinux from scratch

Build an SELinux-ready Gentoo system

Level: Intermediate

Serge E. Hallyn ([email protected]), Staff Programmer, IBM

11 May 2006

SELinux, the U.S. National Security Agency's implementation of mandatory access control, is the most prominent new security subsystem in Linux®. It comes installed by default in Fedora and Red Hat Enterprise Linux and is available in easy-to-install packages in other distributions. This article shows you how to convert a non-SELinux system by hand in order to expose details about how SELinux is integrated into a system.

Introduction

SELinux is a mandatory access control (MAC) system available in Linux kernels as of version 2.6. Of the Linux Security Modules available, it is the most comprehensive and well tested, and is founded on 20 years of MAC research. SELinux combines a type-enforcement server with either multi-level security or an optional multi-category policy, and a notion of role-based access control. See the Resources section later in this article for links to more information about these topics.

Most people who have used SELinux have done so by using an SELinux-ready distribution such as Fedora, Red Hat Enterprise Linux (RHEL), Debian, or hardened Gentoo. These enable SELinux in the kernel, offer a customizable security policy, and patch a great number of user-land libraries and utilities to make them SELinux aware.

If you're like many users who simply want the system to work as before, but a bit more securely, you can query and manipulate SELinux by using familiar applications and by writing security policies using a higher level language. However, these methods can be insufficient when something breaks -- such as when kernel and user-space get out of sync. Also, these methods might even hinder the UNIX® engineer from understanding how SELinux is actually working. Finally, the engineer and the security community should understand that there are appropriate ways to use SELinux outside of the conventions in use by current distributions.

In this article, learn how to convert a system that is initially completely unaware of SELinux into one that enforces SELinux. You also learn how to enforce a few simple access policies.





Preliminaries

To get started, you need:

  • QEMU, a freely available and easy-to-use processor emulator. It is an excellent way to play with new kernels or system images without doing harm to your real system. You can download it from the QEMU download page.
  • Gentoo, a source-based Linux distribution. Gentoo is ideal for this exercise, since you can install it under a running system regardless of the distribution. Find the latest version at the Gentoo download page.

Create a disk image by typing:

qemu-img create -f raw gentoo.img 2G

The next step is to start up QEMU to partition the raw disk image and format a single partition. This requires some sort of Linux boot CD. Knoppix will do, as will a Gentoo liveCD. You can download a Gentoo liveCD as follows:

wget ftp://ftp.gtlib.cc.gatech.edu/pub/gentoo/releases/x86/current/installcd/install-x86-minimal-2006.0.iso

For easier future reference -- and less typing -- you might want to rename the image:

mv install-x86-minimal-2005.1.iso gentoo.iso

The following command instructs QEMU to use gentoo.iso as its CD, use gentoo.img as its hard disk, and boot from the CDROM:

qemu -hda gentoo.img -cdrom gentoo.iso -boot d

Just hit Return for the default kernel. Then, type the following to partition the disk image:


Listing 1. Partition a disk image

 fdisk /dev/hda n p 1 (return) w 

The above listing creates a single new (n) primary (p) partition beginning at block 1 (1) and ending at the default ending block, which is the last block on the file system. It then writes (w) the new partition table to the disk image.

Now, you will be returned to the shell prompt in QEMU. Here, type:

mkfs.ext2 /dev/hda1

You may have to do that twice in order to give udev a chance to create the device. Then, shut down by typing:

poweroff

This returns you to your real system's shell. If it does not, and hangs for a long time, hit Ctrl-c to end it.

The next step is to lay a basic distribution down on the disk image. One reason Gentoo is a great fit for this exercise is because you can simply download and extract a "stage 3" image, giving you a functional Gentoo system. You should find a local mirror from which to download a stage 3 tarball. An example location, if you are located near Sandia National Laboratories, is:

wget ftp://mirror.iawnet.sandia.gov/pub/gentoo/releases/x86/current/stages/stage3-x86-2006.0.tar.bz2

This file contains a compressed archive of a full Gentoo system. To extract this into your disk image, first mount the disk image onto your system. The following listing mounts the empty file system and expands the tarball onto it.


Listing 2. Extract Gentoo tarball onto disk image

 su (give root password) ORIG=`pwd` mount -oloop,offset=32256 gentoo.img /mnt cd /mnt tar jxf $ORIG/stage3-x86-2005.1.tar.bz2 

While the image is still mounted, there are a few more preliminaries to take care of. The /etc/fstab file instructs the system which file systems to mount where. For this simple system, no boot or swap entries are needed. The following listing removes those and inserts a correct entry for the root partition. It also sets the password for the root user. Make sure that when running passwd, you pick a password you remember. Security is not a concern for this toy system, so "password" will do.


Listing 3. System preliminaries

 mv /mnt/etc/fstab /mnt/etc/fstab.orig sed -e '/[BR]OOT/d' -e '/SWAP/d' /mnt/etc/fstab.orig > \ /mnt/etc/fstab cat >> /mnt/etc/fstab << EOF /dev/hda1 / ext2 noatime 0 1 EOF chroot /mnt passwd exit cd $ORIG umount /mnt 

A kernel is needed for the QEMU image to boot. Simply compile this with SELinux support now, even though you won't be using SELinux just yet. Grab a copy of linux-2.6.14.tar.bz2 (or the latest version) from kernel.org and extract it:

wget http://kernel.org/pub/linux/kernel/v2.6/linux-2.6.14.tar.bz2
tar jxf Linux-2.6.14.tar.bz2

Then, change into the Linux-2.6.14 directory and configure the kernel, like so:

cd linux-2.6.14
make defconfig
make menuconfig

Make sure to enable at least the following options:


Listing 4. Excerpts from kernel .config

 CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_SECURITY=y CONFIG_SECURITY=y CONFIG_SECURITY_CAPABILITIES=y CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SELINUX_BOOTPARAM=y CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 CONFIG_SECURITY_SELINUX_DISABLE=y CONFIG_SECURITY_SELINUX_DEVELOP=y CONFIG_SECURITY_SELINUX_AVC_STATS=y CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 

Now, compile this kernel using the following command:

make
cp arch/i386/boot/bzImage ..

Surely, you'd like to test this system before converting to SELinux. You can do this using this command:

qemu -hda gentoo.img -kernel bzImage -append "ro root=/dev/hda1"

Look around, add some users, and play with your system. When you're done, shut it down using poweroff. Now, you're ready to begin converting this system to SELinux.





Converting to SELinux

To convert this system to one that supports and enforces SELinux, you need to modify the program that begins booting the system, /sbin/init, and add a few other pieces of software to build SELinux policy and interact with SELinux.

SysVinit

Begin by grabbing a clean copy of SysVInit. Download version 2.86 from ftp://ftp.cistron.nl/pub/people/miquels/sysvinit/sysvinit-2.86.tar.gz, or look for the latest version on the SysVinit page on freshmeat. You can download a patch (sysvinit-init.c.diff) in the zip file available in the Downloads section, below; this patch will be applied on top of the file init.c using the procedure in Listing 5. This patch causes the SELinux policy to be loaded at boot. It introduces a flag no_selinux, which is set to 1 if the boot command includes -p. If that flag is set, a warning is given and boot proceeds as normal. Otherwise, the function load_policy(), which is defined further in the patch, is called.


Listing 5. Partition a disk image

 wget ftp://ftp.cistron.nl/pub/people/miquels/sysvinit/sysvinit-2.86.tar.gz cd sysvinit-2.86 cd src patch -p0 < $ORIG/sysvinit-init.c.diff make init (su) mount -oloop,offset=32256 $ORIG/gentoo.img /mnt mv /mnt/sbin/init /mnt/sbin/init.good cp init /mnt/sbin/init umount /mnt exit 

The function load_policy() mounts an instance of the selinuxfs file system on the directory /selinux, and opens the file /etc/policy.bin for reading. Note that both /selinux and /etc/policy.bin are arbitrary names so long as any userspace tools that might want to use them agree on the naming. When an SELinux policy is compiled, the binary version will need to be copied to /etc/policy.bin. Next, load_policy() mmap()s the file /etc/policy.bin, and calls security_load_policy, which is defined immediately above load_policy. It, in turn, opens the file /selinux/load, which is a file in the selinuxfs file system, for writing, and writes the entire contents of /etc/policy.bin into /selinux/load. This is how the binary policy will be loaded into the kernel at boot.

Creating a policy

SELinux is a flexible access control system whose access decisions are guided by an administrator-definable policy. Policies depend on the layout and configuration of files on the system. Distributions that support SELinux come with a predefined policy. While it is possible to edit the policy, you generally edit policy only to the extent of excluding whole chunks of policy relating to software not installed on the system. More detailed policy editing generally belongs to the realm of SELinux experts. However, in this exercise, you will define your own policy.

Because new object classes and permissions are introduced from time to time, policies end up being somewhat dependent on kernel versions. The program located in mdp.tar.gz (in the zip file in the Downloads section, below) will automatically construct a dummy policy based on your kernel version. Since it will need to analyze the kernel source, you will need to point it at the source tree that you used to compile the kernel for the QEMU image. Extract mdp.tar.gz into $ORIG/ and enter the resulting directory, mdp/.

Type:

./build.sh -k ../linux-2.6.14.

This compiles the program mdp and runs it with the kernel directory as an argument. mdp in turn looks at the object classes and permissions that the kernel knows about and creates an SELinux policy containing this data. The resulting policy will have one SELinux user, one SELinux role, and one SELinux type. The single type will be applied to all files, kernel objects, and processes, and will have full access to itself. We will play with customizations to this policy later, but for now it is sufficient to initialize and use SELinux.

When build.sh runs mdp, it will create several files. You need policy.conf and file_contexts. The former is the text representation of the policy, the latter contains the instructions for how to label the file system.

I'll defer a comprehensive study of policy.conf for now, so skip the first five or six hundred lines to this line:

type base_t;

This is the only type defined in this policy. The next line:

role base_r types { base_t };

defines a single role, base_r, which is associated with type base_t. This means that a process in role code_r may run under domain base_t. Next comes a long list of allow statements, one specifying each object class, giving the process under domain base_t access to the object classes of type base_t for all permissions defined for the class.

Next, the policy defines a user, user_u, which is associated with role base_r. A process that is running as SELinux user user_u, then, can run under role base_r. You've already seen that base_r is associated with type base_t, so these two statements together make user_u:base_r:base_t a valid context, meaning a process will be allowed to run under that context.

The next few lines are also of interest. The first:

sid kernel user_u:base_r:base_t

assigns the single valid context to the first process on the system. Two lines later, you see:

sid unlabeled user_u:base_r:base_t

which assigns the same context to any files that are otherwise unlabeled.

Now take a look at the file called file_contexts. It contains two lines. The format is:

<regexp> <context>

where regexp is a regular expression used to compare against file names, and context is an SELinux context to apply to a file if it matches the regular expression. The line:

/.* user_u:base_r:base_t

is used to assign the context to all files on the system.

Installing SELinux userspace

The next step is to install some code that will compile the SELinux policy, which you've written in text form, to the binary format, which the kernel requires, as well as a program to label your root file system. The source is available through CVS from SourceForge by using the command shown in Listing 6:


Listing 6. Check out SELinux userspace source

 su mount -oloop,offset=32256 $ORIG/gentoo.img /mnt cd /mnt/usr/src cvs -z3 -d:pserver:[email protected]:/cvsroot/selinux co -P \ nsa/selinux-usr 

Copy the plain text policy onto the disk image, like so:

cp -r $ORIG/mdp /mnt/usr/src

Enter the nsa/selinux-usr directory, and compile libsepol, checkpolicy, libselinux, and policycoreutils, as follows:


Listing 7. Compile SELinux userspace code

 chroot /mnt cd /usr/src/nsa/selinux-usr/ cd libsepol/ make && make install cd ../libselinux/ make && make install cd ../checkpolicy/ make && make install cd ../policycoreutils/ make && make install 

If you encounter an error during the last step, make certain that setfiles is installed by typing this:


Listing 8. Install setfiles

 cd setfiles make make install 

Now, to compile the policy, use the checkpolicy program like this:


Listing 9. Compile SELinux policy

 cd /usr/src/mdp checkpolicy -o policy.bin policy.conf cp policy.bin /etc/ exit # exit chroot exit # exit root shell 

Relabeling the file system requires booting into the virtual machine. Remember to specify the -p option for now, so that /sbin/init will not attempt to load an SELinux policy:

qemu -hda gentoo.img -kernel bzImage -append "ro root=/dev/hda1 -p"

SELinux interacts with userspace programs through its own file system, selinuxfs. The userspace programs expect this to be mounted under /selinux. Create the /selinux directory and relabel the file system, as follows:


Listing 10. Relabel the file system

 mkdir /selinux cd /usr/src/mdp setfiles file_contexts / poweroff 

Finally, you can reboot under SELinux!

qemu -hda gentoo.img -kernel bzImage -append "ro root=/dev/hda1"

Studying the SELinux policy

SELinux makes access decisions based on the security contexts assigned to processes, files, and other objects. SELinux provides interfaces for querying these contexts and, given the required access rights, to set them. For instance, SELinux reports process contexts through the procattr interface. If you type:

cat /proc/$$/attr/current

you see the context of the current process ($$). By using the script pidctx.sh (see the zip file in the Downloads section, below), you can easily view the context of all processes on the system. The script simply prints the /proc/<pid>/attr/current file for each process on the system.

SELinux stores file contexts using extended attributes. Most persistent file systems under Linux (ext2, ext3, jfs, xfs, etc.) support extended attributes, though reiserfs is an unfortunate notable exception. These are (name, value) pairs of data that are associated with inodes, where the name is separated by periods into namespaces. The SELinux extended attributes are in the security namespace and identified by "selinux", so the full name of the xattr value is "security.selinux". A new set of system calls allows userspace to query and set extended attributes. The system call to query an xattr is getxattr(2). It takes a file name, an attribute name, a buffer in which to return the value of the xattr, and the size of the provided buffer.

The showctx.c file simply runs through all the file names provided as command line arguments and prints the value of the security.selinux extended attribute, provided that it exists, is readable, and fits within a reasonable size.

You can download showctx.tar.gz from the zip file in the Downloads section, below, and extract showctx.c. Then get it into your QEMU machine some way. One way is to shut down the QEMU image and then do this:


Listing 11. Install showctx

 (su) mount -oloop,offset=32256 $ORIG/gentoo.img /mnt cp showctx.c /mnt/usr/src umount /mnt exit 

Now start QEMU, if it is not already running. To compile showctx, type:

gcc -o showctx showctx.c cp showctx /bin/

Now you can type:

showctx / /tmp /home /root /usr/src

Of course, you'll see the same context for each file. The next section makes this somewhat more interesting by enhancing the policy.



Back to top


Playing with SELinux policy

Secret type

You'll create a secret directory, /secret, under which SELinux should allow no process to read. Begin by actually creating the directory and a few files under the directory:

mkdir /secret echo "hello, world" > /secret/helloworld echo "You can't see me" > /secret/dontlook

In the SELinux policy, now create a new type, secret_t, to which the other type, base_t, has no permissions. First, you define the type by adding:

type secret_t;

after the declaration of base_t in policy.conf. In addition, since the files of type secret_t will be of role base_r, the role base_r must be allowed to associate with secret_t. The line following the one you just added reads:

role base_r types { base_t };

Edit this to read:

role base_r types { base_t secret_t };

Now, to recompile this policy, type:

checkpolicy -o policy.bin policy.conf
cp policy.bin /etc/

Next add the following lines to the file_contexts file:


Listing 12. File contexts for /secret

 /secret user_u:base_r:secret_t /secret/helloworld user_u:base_r:base_t /secret/.* user_u:base_r:secret_t 

This tells the system that the directory /secret, and any file name underneath it, should be of type secret_t, except for the file /secret/helloworld, which should still be of type base_t. To assign these contexts on disk, use setfiles:

setfiles file_contexts /

Oh no, an error! SELinux doesn't yet know about the type secret_t. It is, in fact, possible to dynamically reload the SELinux policy. For now, however, for the sake of simplicity, just reboot the QEMU image. Of course, since a bootloader was never installed, a simple reboot won't work. Therefore, you need to type poweroff to shut down the QEMU image. If the window does not disappear after "Power down" is printed, then Ctrl-c the qemu command. Rerun the qemu command to restart it. Then try running the above setfiles command again.

Verify that the policy reload worked:

showctx / /secret /secret/helloworld /secret/dontlook cat /secret/dontlook

But wait! You can see the secret types.

This is the result of one of the compile time kernel options, CONFIG_SECURITY_SELINUX_DEVELOP. This option defaults SELinux into non-enforcing mode. To verify this, type:

cat /selinux/enforce

which should return 0. To set SELinux into enforcing mode, type:

echo 1 > /selinux/enforce

You could do this automatically at boot through an init script if you wanted to, as in Listing 13, or simply compile a kernel without SELINUX_DEVELOP support.


Listing 13. Set SELinux enforcing mode on boot

 cat >> /etc/rc.d/selinux-enforce << EOF #!/bin/sh echo 1 > /selinux/enforce EOF chmod ugo+x /etc/rc.d/selinux-enforce rc-update add default selinux-enforce 

Now that SELinux is in enforcing mode, try browsing under /secret again. Note that even though your process context has the rights to read /secret/helloworld, you can't actually read it because you cannot get past /secret. A hardlink to the file could, of course, bypass this. This is not true for other files under /secret/, because the files themselves are unreadable.




Conclusion

In this article, you've seen how to reproduce much of the work that has already been done in some distributions to incorporate SELinux. If it seemed daunting, rest assured -- by simply installing a fresh copy of recent Fedora, you can be running SELinux so transparantly that you may not even know it is installed. The point of this excercise, then, was not to persuade you that security is intrusive, but rather to explain some of what goes on behind the scenes in a properly integrated SELinux system.






Download

Description Name Size Download method
Scripts and C code described in this article l-selinux.zip 4KB HTTP
Information about download methods Get Adobe® Reader®




Resources

Learn

  • Learn more about SELinux at the NSA's Security-Enhanced Linux (SELinux) home page.

  • Implementing SELinux as a Linux Security Module gives an overview of LSM as well as details about the LSM implementation of SELinux and how it differs from the original kernel patch implementation.

  • SELinux News is a community news site for the SELinux community.

  • At the Linux Security Modules site, learn more about LSM.

  • Wikipedia gives overviews of mandatory access control, type enforcement, role-based access control, and multilevel security.

  • To learn more about Knoppix, read "Knoppix gives bootable, one-disk Linux" (developerWorks, February 2003).

  • Also check out "Distribute software on a Linux LiveCD" (developerWorks, January 2006) for links to other LiveCD articles.

  • "Secure programmer: Minimizing privileges" (developerWorks, May 2004) discusses traditional and new methods for decreasing security vulnerabilities.

  • In the developerWorks Linux zone, find more resources for Linux developers.

  • Stay current with developerWorks technical events and Webcasts.


Get products and technologies

  • The QEMU home page has the latest documentation and downloads for QEMU.

  • gentoo.org is your main resource for Gentoo news and code.

  • Get the most recent version of SysVinit from freshmeat.

  • Order the SEK for Linux, a two-DVD set containing the latest IBM trial software for Linux from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.

  • With IBM trial software, available for download directly from developerWorks, build your next development project on Linux.


Discuss





About the author

Serge Hallyn is a Staff Programmer with the IBM Linux Technology Center's security team. He obtained his Ph.D. in computer science from the College of William and Mary. He has implemented several security modules (dte, bsdjail), contributed to others (seclvl), and has contributed to the SELinux effort. Thanks to his implementation of DTE and corresponding configuration and analysis tools, he has extensive experience in Type Enforcement, the primary technology in SELinux.

相关阅读 更多 +
排行榜 更多 +
僵尸猎手小明

僵尸猎手小明

动作格斗 下载
狩猎波比

狩猎波比

动作格斗 下载
花海相机

花海相机

图像拍照 下载