Copyright © 2001 Data Deliverance Pty Ltd
This README, patch and associated utility programs (if any) are released under the GNU Public License Version 2.

Immutable and Append-Only Device Files

Introduction

Files which are marked immutable may not be written to, even by root, and regardless of the file permissions. Similarly, append-only files may be written to only in append mode. Log files are good candidates for append-only files, allowing only new logs to be added.

Devices files for things like raw disks and kernel memory are good candidates for immutable files, since this stops fiddling with the disk or memory images, subverting security.

In current kernels, attributes such as immutable and append-only appear to be implemented only for the ext2 filesystem, as a local addition. Furthermore, setting attributes on device files is not implemented. This patch provides a standard system-call interface for setting and getting attributes, and extends the ext2 support to allow applying attributes on any file.

Note: As it stands, on a standard system, the immutable and append-only support that Linux provides is not as useful as it might be, since root can still turn off these attributes and do whatever is necessary to the file. The splitting of privileges into different capabilities can alleviate this problem, but user-level capability support is still fairly immature.

Our company's Fort of Deliverance firewall and secure application server platform makes good use of immutable and append-only files, but adds additional checks to ensure that immutable and append-only files cannot be tampered with when the system has fully booted.

Installation

This distribution includes: This is a source patch distribution. You can also order a CD containing a fully compiled kernel, modules and relevant executables, with automatic instaler. Click here for more information.

The installation process involves three steps:

  1. Patch, compile and install the kernel
  2. Patch, compile and install the ext2 fsck commands
  3. Compile and install the attribute changing commands

Patching and installing the kernel

To install the kernel patch you will need:

To install, do the following:

  1. Download the patch file.
  2. Change into the kernel source directory (e.g. /usr/src/linux-2.4)
  3. Patch the kernel, like this:
    # patch -p1 < path-to-patch-file
    

    This may generate quite a few messages. If you get any errors indicating that patches have been rejected, your kernel is not fully compatible with the patch. If you do not have good knowledge of the inside workings of the kernel, you may be advised to upgrade to a kernel which is supported. See also our consulting services.

  4. Configure the kernel

    If you have not customised or compiled your kernel before, you will need to do this step. Type:

    # make xconfig
    
    You should get a window up with many buttons. If you are using the 2.4 kernel you should know what to do from here. For a default configuration (not necessarily the right choice) click on the button labeled "Save and exit".

  5. Compile the kernel

    Type these commands to set up and compile the kernel and modules:

    # make dep
    # make bzImage modules
    

  6. Install the new kernel and modules

    WARNING: You are about to replace the kernel, the heart of the system. If you get this wrong, you may render your system unbootable and have to salvage it from the install disk. Follow the steps below to ensure that you can still boot if something goes wrong.

    NOTE: These instructions relate to systems running lilo (if you get the "lilo:" prompt when your system boots). For other systems you will need to find out how to safely replace the kernel.

    First, rename the old kernel. It should live in /boot, and should be called something like "vmlinuz-some-version" - e.g. "vmlinuz-2.4.0". Rename it to have the extension ".old". It is safe to do this while the system is running. For example:

    # cd /boot
    # mv vmlinuz-2.4.0 vmlinuz-2.4.0.old
    

    Now copy the new kernel into the /boot directory. It should live in your "/usr/src/linux" directory under the "arch/i386/boot" subdirectory (or "arch/something-else/boot" if you are not using a PC), and should be called "bzImage". Copy it over and call it "vmlinuz-2.4.0". Make sure that you have renamed the old kernel first, if it had the same name. Also make the "vmlinuz" kernel link point to the new kernel. For example:

    # cd /usr/src/linux/arch/i386/boot
    # cp -i bzImage /boot/vmlinuz-2.4.0
    # mv /boot/vmlinuz /boot/vmlinuz.old
    # ln -s vmlinuz-2.4.0 /boot/vmlinuz
    

    Now time to install and set up the kernel modules. Check to see if you have a directory called "2.4.0" in /lib/modules. If so, rename it to "2.4.0.old". Similarly, if you have a file called "/boot/System.map-2.4.0", rename it as well. Copy the file called "System.map" in your kernel build directory to "/boot/System.map-2.4.0". For example:

    # cd /usr/src/linux/
    # cp -i System.map /boot/System.map-2.4.0
    
    Now in the directory where you compiled the kernel, type:
    # make modules_install
    
    Following this, you will need to make the system map and module info like this:
    # cd /boot
    # mv System.map System.map.old
    # ln -s System.map-2.4.0 System.map
    # depmod -a -i -m /boot/System.map-2.4.0 2.4.0
    

    Now back up the file "/etc/lilo.conf" - call it "/etc/lilo.conf.orig" or something like that. This is a critical system file and you are about to make changes in it. If is safe to do this, but make sure you have a backup first. The file should look something like this, plus or minus a few lines:

    boot=/dev/hda
    map=/boot/map
    install=/boot/boot.b
    prompt
    timeout=50
    linear
    default=linux
    image=/boot/vmlinuz-2.4.0
    	label=linux
    	initrd=/boot/initrd-2.4.0.img
    	read-only
    	root=/dev/hda5
    

    There may be more than one section starting "image=". If so, find the one with a "label=" parameter matching the "default=" near the top. So for example if your file has "default=linux", you should search for an image section with "label=linux" in it. Normally you will have only one image section anyway. Duplicate the section starting "image=" to the end of the file, or until the next "image=" line.

    Edit the old image section, adding ".old" onto the end of the label, and onto the end of the image line. In the example, the file would now look like this:

    boot=/dev/hda
    map=/boot/map
    install=/boot/boot.b
    prompt
    timeout=50
    linear
    default=linux
    image=/boot/vmlinuz-2.4.0.old
    	label=linux.old
    	read-only
    	root=/dev/hda5
    image=/boot/vmlinuz-2.4.0
    	label=linux
    	read-only
    	root=/dev/hda5
    

    Finally, run the command "lilo". If you get any errors, make sure you have copied the file with the correct name, and that there are no mistakes in the /etc/lilo.conf file.


    If you cannot get it to work, do not reboot the computer without doing the following:

    For example:
    # rm /etclilo.conf
    # mv /etc/lilo.conf.old /etc/lilo.conf
    # cd /boot
    # rm vmlinuz System.map
    # mv vmlinuz.old vmlinuz
    # mv System.map System.map.old
    # lilo
    

    Assuming you have it working, now reboot your system. If it fails to boot, you can back out of the patch by doing the following:

    Your system should now be back where it started.


    Patching and installing the ext2 fs commands

    The fsck command for the ext2 filesystem is patched so that it does not clear the immutable and append-only flags on devices. The patch is based on the e2fprogs package (version 1.19), obtainable from e2fsprogs.sourceforge.net.

    Make sure you don't download an earlier version of e2fsprogs from what you are using on your system. The latest version should generally be safe. If you are using RPMs, you can find out what version you currently have using a command such as this:

    # rpm -q -f /sbin/e2fsck
    

    Before going further, make sure that you can back out of this installation if anything goes wrong. You should have ideally backed up your system, or at least have access to the version of the e2fsprogs package that is installed on your system so you can reinstall it later if necessary.

    If you downloaded the RPM version (make sure it is the source RPM), install the source, then patch it. On a RedHat system, you might do that like this:

    # rpm -i e2fsprogs-1.19-0.src.rpm
    # rpm -bp /usr/src/redhat/SPECS/e2fsprogs.spec
    # cd /usr/src/redhat/BUILD/e2fsprogs-1.19
    # patch -p1 < path-to-patch-file/e2fsprogs-patch-1.19-attr
    
    If you downloaded a tar.gz file or some such, extract it, change into the e2fsprogs-1.19 directory created (or whatever it is called), and run the patch command above.

    Now, for an RPM, build and install with commands like this:

    # rpm -bi /usr/src/redhat/SPECS/e2fsprogs.spec
    
    For a non-RPM install, follow the instructions in the INSTALL file.

    Compiling and installing the utilities

    To compile and install the utilities, go to the "progs" subdirectory in the patch distribution. If you have not patched the files for the current kernel, or /usr/include/linux does not point to the kernel source you patched, then uncomment the CFLAGS= line in the Makefile to point to your kernel include directory root (e.g. /usr/src/linux/include). Finally, just type "make install" to create and install two binaries - lsattr and chattr. The old lsattr and chattr should be renamed to lsattr.ext2 and chattr.ext2. They may still be useful, as described below.

    Using the Utilities

    chattr and lsattr work in much the same as their ext2 counterparts, as described by the manual pages. Only the generic attributes A, a, i and S flags are supported by chattr. Only -R is supported as a flag by lsattr and chattr.

    Note that lsattr.ext2 and chattr.ext2 are quite compatible with the generic ones: using chattr.ext2 to set a flag on a plain file has the same effect as using the generic chattr. chattr.ext2 can be used to set flags that are specific to the ext2 filesystem, not available with the generic chattr, and lsattr.ext2 can be used to list these flags.


    Matthew Donaldson <matthew@datadeliverance.com>
    Last modified: Sat Mar 30 23:14:16 CST 2002