CaitSith -- A simplified access restriction module for system protection.

CaitSith is an access restriction module for Linux systems. This module gives you ability to restrict access (e.g. opening files, executing programs) at the kernel level. This module is designed for ease of use.


Index

1. Difference with TOMOYO (for existing TOMOYO users)

2. How to install

3. How to develop policy

4. List of conditions

5. List of syntaxes

6. Advanced usage


1. Difference with TOMOYO (for existing TOMOYO users)

CaitSith was derived from TOMOYO Linux, but usage of CaitSith would be too different to imagine that CaitSith was derived from TOMOYO Linux. If you are already using TOMOYO Linux, please read the difference described below.


1.1. About pathnames and management programs

/proc/ccs/domain_policy , /proc/ccs/exception_policy , /proc/ccs/profile , /proc/ccs/manager and /proc/ccs/stat have been aggregated into /sys/kernel/security/caitsith/policy .

/etc/ccs/policy/current/domain_policy.conf , /etc/ccs/policy/current/exception_policy.conf , /etc/ccs/policy/current/profile.conf , /etc/ccs/policy/current/manager.conf and /etc/ccs/policy/current/stat.conf have been aggregated into /etc/caitsith/policy/current .

Built-in policy files which are located under kernel source directory as security/ccsecurity/policy/domain_policy.conf , security/ccsecurity/policy/exception_policy.conf , security/ccsecurity/policy/profile.conf , security/ccsecurity/policy/manager.conf and security/ccsecurity/policy/stat.conf have been aggregated into security/caitsith/policy/policy.conf .

Only /sbin/caitsith-init , /usr/sbin/caitsith-auditd , /usr/sbin/caitsith-loadpolicy , /usr/sbin/caitsith-notifyd , /usr/sbin/caitsith-pstree , /usr/sbin/caitsith-queryd , /usr/sbin/caitsith-savepolicy , /usr/lib64/caitsith/audit-exec-param , /usr/lib64/caitsith/caitsith-agent and /usr/lib64/caitsith/init_policy are provided for managing policy. (In other words, programs such as /usr/sbin/ccs-editpolicy and /usr/sbin/ccs-setprofile have been removed.)

Command line arguments for specifying type of policy to load/save have been removed from /usr/sbin/caitsith-loadpolicy and /usr/sbin/caitsith-savepolicy .

Command line arguments for specifying profile type have been removed from /usr/lib64/caitsith/init_policy .


1.2. About policy syntax

Policy syntax has been drastically changed. TOMOYO Linux uses process's domainname as a key for grouping permissions to do some operations. In other words, TOMOYO Linux's policy is collection of "which domain can do ..." rules. On the other hand, CaitSith uses operation as a key for checking permission. In other words, CaitSith's policy is collection of "which operation can be done by ..." rules. This change is intended for allowing users to protect resources using denylisting approach. In CaitSith, process's domainname is nothing but one of optional parameters that can be used for controlling whether to allow or deny specific operations. Users can write rules without managing domainnames unless needed.

Process's domainname representation has changed from space delimited multiple words (e.g. "<kernel> /sbin/init /etc/rc.d/rc.sysinit") to a single word (e.g. "/sbin/init").

Domain transitions no longer happen unless explicitly specified by policy.

Distinction of disabled/learning/permissive/enforcing mode has been removed.

"path_group" keyword has been renamed to "string_group", and "address_group" keyword has been renamed to "ip_group".

Representation of \ character has been changed from \\ to \134.

Distinction between directory's pathname and non-directory's pathname has been removed by removing trailing / character from pathname.

A new wildcard /\(dir\)/ has been introduced for helping converting from (e.g.) "/tmp/\{\*\}/" to "/tmp/\(\*\)/\*", for directory's pathname (except the root directory itself) no longer ends with / character which previously matched /\{\*\}/ wildcard.

Category keywords (i.e. "file", "network", "ipc", "misc", "capability", "task") have been removed because access control levels which was specified using profile has been removed. Some of operation keywords have been renamed (e.g. "network inet stream connect" became "inet_stream_connect", "misc env" became "environ").

"task auto_execute_handler" keyword has been renamed to "handler=" argument of "execute" keyword. This is intended for using execute handler for preprocessing purpose when executing specific programs rather than when executing from specific domains. "task denied_execute_handler" keyword has been removed.

Domain argument has been removed from permission to send signals (i.e. "signal" directive), for kill() system call accepts negative number for specifying multiple processes. It is impossible to selectively deny sending signals because it is not permitted to sleep while sending signals.

Restriction granularity for ptrace operation has changed from boolean (i.e. "capability SYS_PTRACE") to command number + domainname.

Restriction granularity for environment variables has changed from name only to both name and values.

Several variables for referencing file's attributes have been added.

Local port reserve functionality (i.e. "deny_autobind" keyword) has been removed.


1.3. Why CaitSith was developed?

Presentation slides which I used at LinuxCon North America 2012 that explain why CaitSith was developed are available.


2. How to install

CaitSith supports Linux kernel 2.6.27 and later.

There are two ways to compile CaitSith kernel module. Please choose one, but please accept that you need to choose fully featured version if you can't choose LKM-based LSM version.

LKM-based LSM versionfully featured version
AdvantagesNo need to replace kernel package.Complete functionality and syntax are supported.
DisadvantagesSupported functionality and syntax depend on kernel's version and kernel's configuration options.Need to replace kernel package.
Dependency Kernel package must be built with below configuration options.
  • CONFIG_SECURITY=y
  • CONFIG_KALLSYMS=y
  • CONFIG_PROC_FS=y
  • CONFIG_MODULES=y
The kernel package should be built with below configuration options in addition to above configuration options for supporting further functionality.
  • CONFIG_SECURITY_NETWORK=y
  • CONFIG_SECURITY_PATH=y
Currently known to work on x86_32 x86_64 SH and ARM. Other architectures are not tested yet.
Requires patching against kernel's source and rebuilding from source.

2.1. How to install LKM-based LSM version


2.1.1. Install dependencies

These packages are required for compiling the kernel module and the userspace tools:

These can be installed with the following commands:

RedHat distributions

# yum -y install wget gcc make ncurses-devel

Debian distributions

# apt-get -y install wget gcc make libncurses-dev

SUSE distributions

# yast -i wget gcc make ncurses-devel

2.1.2. Extract source code

Install the kernel development package and go to the directory that it has installed into:

RedHat distributions

# VERSION=$(uname -r)
# yum -y install kernel-devel-${VERSION}
# cd /usr/src/kernels/${VERSION}*/

Debian distributions

# VERSION=$(uname -r)
# apt-get -y install linux-headers-${VERSION}
# cd /usr/src/linux-headers-${VERSION}/

SUSE distributions

# VERSION=$(uname -r)
# yast -i kernel-devel
# cd /lib/modules/${VERSION}/build/

Run the following commands in order to extract source code of CaitSith:

# wget https://sourceforge.net/projects/tomoyo/files/caitsith-patch/0.2/caitsith-patch-0.2-20250415.tar.gz
# wget https://sourceforge.net/projects/tomoyo/files/caitsith-patch/0.2/caitsith-patch-0.2-20250415.tar.gz.asc
# wget https://tomoyo.sourceforge.net/kumaneko-key
# gpg --import kumaneko-key
# gpg caitsith-patch-0.2-20250415.tar.gz.asc
# tar -zxf caitsith-patch-0.2-20250415.tar.gz

2.1.3. Edit build options

2.1.3.1. Changing activation trigger

On systemd environments, /usr/lib/systemd/systemd will be executed rather than /sbin/init . If your system is using systemd, please edit CONFIG_CAITSITH_ACTIVATION_TRIGGER line in caitsith/config.h like below unless you choose Loading CaitSith's module from the init process:

Before:

#define CONFIG_CAITSITH_ACTIVATION_TRIGGER "/sbin/init"

After:

#define CONFIG_CAITSITH_ACTIVATION_TRIGGER "/usr/lib/systemd/systemd"

2.1.3.2. Omitting userspace policy loader

There are two types of CaitSith's policy configuration. The former is embedded into the kernel and the latter is saved as files on the filesystems (e.g. /etc/caitsith/ directory). You will need to rebuild the CaitSith kernel module whenever updating the former, but allows you to load policy without using userspace policy loader (e.g. /sbin/caitsith-init ). The latter is loaded by executing userspace policy loader when the access control by CaitSith is about to be activated (e.g. when /sbin/init or /usr/lib/systemd/systemd starts).

If you want to activate CaitSith as soon as the kernel module is loaded, you can define CONFIG_CAITSITH_OMIT_USERSPACE_LOADER line in caitsith/config.h like below. (But be sure to supply built-in policy configuration located at caitsith/policy/ directory if you define CONFIG_CAITSITH_OMIT_USERSPACE_LOADER, or the system will panic as soon as the kernel module is loaded.):

Before:

//#define CONFIG_CAITSITH_OMIT_USERSPACE_LOADER

After:

#define CONFIG_CAITSITH_OMIT_USERSPACE_LOADER

2.1.4. Compile and install the kernel module

Run the following commands in order to build and install CaitSith:

# make SUBDIRS=$PWD/caitsith modules
# make SUBDIRS=$PWD/caitsith modules_install
# depmod ${VERSION}

If you encountered one of errors listed below, you cannot use CaitSith for your kernel. Please jump to 2.2. How to install fully featured version. For other errors, please contact the author ( penguin-kernel@I-love.SAKURA.ne.jp ).

You must choose CONFIG_SECURITY=y for building this module.
You must choose CONFIG_KALLSYMS=y for building this module.
You must choose CONFIG_PROC_FS=y for building this module.
You must choose CONFIG_MODULES=y for building this module.

2.1.5. Check whether CaitSith kernel module can be loaded or not (Optional)

Since registering CaitSith module depends on your environment, you might encounter problems. Therefore, I recommend you to confirm that CaitSith module can be loaded at this step.

Run the following commands in order to try to load caitsith_test.ko module:

# dmesg -c > /dev/null
# modprobe caitsith_test
# dmesg
caitsith_test: module verification failed: signature and/or required key missing - tainting kernel
security_ops=ffffffff81df6c80
find_task_by_vpid=ffffffff810821a0
find_task_by_pid_ns=ffffffff81082170
d_absolute_path=ffffffff811c8f10
All dependent symbols have been guessed.
Please verify these addresses using System.map for this kernel (e.g. /boot/System.map-`uname -r` ).
If these addresses are correct, you can try loading CaitSith module on this kernel.

If caitsith_test.ko was loaded successfully, guessed addresses like above are printed. Therefore, please compare guessed addresses from caitsith_test.ko and actual addresses from System.map file. (Number of symbols and addresses printed depends on your environment.):

# for i in ffffffff81df6c80 ffffffff810821a0 ffffffff81082170 ffffffff811c8f10; do grep $i /boot/System.map-${VERSION}; done
ffffffff81df6c80 b security_ops
ffffffff810821a0 T find_task_by_vpid
ffffffff81082170 T find_task_by_pid_ns
ffffffff811c8f10 T d_absolute_path

Please proceed if these addresses are correct.

You might find some gap between guessed addresses from caitsith_test.ko and actual addresses from System.map file (like some examples shown below) if your kernel configuration uses CONFIG_RANDOMIZE_BASE=y. In this case, although guessed addresses will randomly change for every reboot, please proceed as long as the gap between guessed address and actual address is same for all guessed symbols. Otherwise, please contact the author since CaitSith module will not work even if you continue.

If caitsith_test.ko was not loaded successfully, error messages like below are printed. In this case, please contact the author since CaitSith module will not work even if you continue:

# dmesg -c > /dev/null
# modprobe caitsith_test
FATAL: Error inserting caitsith_test (/lib/modules/2.6.32/extra/caitsith_test.ko): Invalid argument
# dmesg
Sorry, I couldn't guess dependent symbols.
I need some changes for supporting your environment.
Please contact the author.

If your kernel has /proc/sys/kernel/kptr_restrict sysctl parameter set to 2, loading of caitsith_test.ko will fail. In this case, please set /proc/sys/kernel/kptr_restrict to 0 before loading and restore /proc/sys/kernel/kptr_restrict to 2 after loading.

# dmesg -c > /dev/null
# echo 0 > /proc/sys/kernel/kptr_restrict
# modprobe caitsith_test
# echo 2 > /proc/sys/kernel/kptr_restrict

2.1.6. Install the userspace tools

Make sure the dependencies described above have been installed. Compile and install the tools with the following commands. (Please use USRLIBDIR=/usr/lib or USRLIBDIR=/usr/lib32 if needed):

$ wget https://sourceforge.net/projects/tomoyo/files/caitsith-tools/0.2/caitsith-tools-0.2-20241111.tar.gz
$ wget https://sourceforge.net/projects/tomoyo/files/caitsith-tools/0.2/caitsith-tools-0.2-20241111.tar.gz.asc
$ gpg caitsith-tools-0.2-20241111.tar.gz.asc
$ tar -zxf caitsith-tools-0.2-20241111.tar.gz
$ cd caitsith-tools/
$ make -s USRLIBDIR=/usr/lib64
$ su
# make -s USRLIBDIR=/usr/lib64 install

Programs listed below are main userspace tools used for administrating CaitSith.

FYI: If your system has rpm-build package installed, you can make a tools RPM package with the following commands:

$ rpmbuild -tb caitsith-tools-0.2-20241111.tar.gz

2.1.7. Initializing configuration

Before you can make use of CaitSith, an initialization procedure must take place. This prepares the files in which policy information will be stored. All policy files are stored in the "/etc/caitsith/" directory.

Run the following command as root user to initialize. (Please use /usr/lib/caitsith/init_policy or /usr/lib32/caitsith/init_policy if needed):

# /usr/lib64/caitsith/init_policy
Creating policy directory... OK
Creating configuration directory... OK
Creating default policy... OK.
Creating module loader... OK.
Creating configuration file for caitsith-auditd ... OK.
Creating configuration file for caitsith-notifyd ... OK.

CaitSith can generate audit logs and allows you to read them via /sys/kernel/security/caitsith/audit interface. To save /sys/kernel/security/caitsith/audit automatically, start /usr/sbin/caitsith-auditd from somewhere. Default setting (specified in /etc/caitsith/tools/auditd.conf ) sends access allowed logs to /dev/null , access unmatched logs to /var/log/caitsith/unmatched.log , access denied logs to /var/log/caitsith/denied.log . (The meaning and example of allowed/unmatched/denied will be explained in Example of simple access restriction rule.)

CaitSith can ask for your decision about access requests which will be denied unless you allow them via /sys/kernel/security/caitsith/query interface. To notify immediately the occurrence of access requests which CaitSith is about to deny, start /usr/sbin/caitsith-notifyd from somewhere. Default setting (specified in /etc/caitsith/tools/notifyd.conf ) sends mails to root@localhost with subject "Notification from caitsith-notifyd" up to once per a minute.

Below example launches /usr/sbin/caitsith-auditd and /usr/sbin/caitsith-notifyd from /etc/rc.d/rc.local script:

#!/bin/bash
# THIS FILE IS ADDED FOR COMPATIBILITY PURPOSES
#
# It is highly advisable to create own systemd services or udev rules
# to run scripts during boot instead of using this file.
#
# In contrast to previous versions due to parallel execution during boot
# this script will NOT be run after all other services.
#
# Please note that you must run 'chmod +x /etc/rc.d/rc.local' to ensure
# that this script will be executed during boot.

touch /var/lock/subsys/local
/usr/sbin/caitsith-auditd
/usr/sbin/caitsith-notifyd

2.1.8. Configuring your bootloader

On systems where use of init= kernel boot option causes boot failures (e.g. earlier versions of RHEL 7), you need to choose Loading CaitSith's module from initramfs. On systems where it does not cause boot failures (e.g. RHEL 6), you can choose Loading CaitSith's module from the init process.

2.1.8.1. Loading CaitSith's module from initramfs

This section assumes that you are using dracut and GRUB2.

Create /etc/dracut.conf.d/caitsith.conf like below and rebuild the initramfs:

# echo 'add_drivers+=" caitsith "' > /etc/dracut.conf.d/caitsith.conf
# dracut -f

Edit your bootloader to add "rd.driver.pre=caitsith" to the kernel boot options. An example is shown below:

Before:

linux16 /boot/vmlinuz-3.10.0-123.9.3.el7.x86_64 ro root=LABEL=/

After:

linux16 /boot/vmlinuz-3.10.0-123.9.3.el7.x86_64 ro root=LABEL=/ rd.driver.pre=caitsith

It is recommended that you also modify GRUB_CMDLINE_LINUX line in /etc/default/grub file like below in case you update kernel packages in the future:

Before:

GRUB_CMDLINE_LINUX="vconsole.keymap=us crashkernel=auto  vconsole.font=latarcyrheb-sun16 rhgb quiet"

After:

GRUB_CMDLINE_LINUX="vconsole.keymap=us crashkernel=auto  vconsole.font=latarcyrheb-sun16 rhgb quiet rd.driver.pre=caitsith"

2.1.8.2. Loading CaitSith's module from the init process

Edit your bootloader (e.g. GRUB) to add "init=/sbin/caitsith-init" to the kernel boot options. An example is shown below:

Before:

kernel /boot/vmlinuz-2.6.32-431.17.1.el6.x86_64 ro root=LABEL=/

After:

kernel /boot/vmlinuz-2.6.32-431.17.1.el6.x86_64 ro root=LABEL=/ init=/sbin/caitsith-init

2.1.9. Rebooting your system

Now you have finished all preparation. Reboot your system.

If everything was installed properly and the bootloader was correctly configured, the kernel should boot as normal and CaitSith should be activated:

caitsith-lsm-activated.png

Note that you won't be able to see CaitSith's messages if you are using "quiet" or "rhgb" kernel boot option because these options prevent most of kernel messages from being printed.

Although CaitSith is a LSM module, CaitSith can coexist with other LSM modules. However, you need to also add "selinux=0" to the kernel boot options if you disable SELinux by specifying SELINUX=disabled in /etc/selinux/config . This is because the init process unregisters LSM hooks which CaitSith module depends on if SELINUX=disabled is specified in /etc/selinux/config .


2.1.10. How can I disable/uninstall CaitSith?

If your system becomes unable to boot during the course of this guide or any time in the future, it may be due to policy configuration or something related to CaitSith. If this is the case, it is possible that the kernel can still be booted by disabling CaitSith. This can be done by removing "rd.driver.pre=caitsith" or "init=/sbin/caitsith-init" from the kernel boot options.

CaitSith fortunately does not require the modification of any existing Linux binaries, libraries or applications. Thus, uninstalling CaitSith is very easy. It is simply a matter of removing "rd.driver.pre=caitsith" or "init=/sbin/caitsith-init" from the kernel boot options and uninstalling the userspace tools that you installed above.


2.2. How to install fully featured version


2.2.1. Install dependencies

These packages are required for compiling the kernel and the userspace tools:

These can be installed with the following commands:

RedHat distributions

# yum -y install wget patch gcc make ncurses-devel

Debian distributions

# apt-get -y install wget patch gcc make libncurses-dev

SUSE distributions

# yast -i wget patch gcc make ncurses-devel

2.2.2. Download and patch the kernel

Download the kernel source from linux-2.6 or linux-3 or linux-4 or linux-5 or linux-6.
Linux kernel 2.6.27 and later are supported from the linux-2.6 tree.
Linux kernel 3.0 and later are supported from the linux-3 tree.
Linux kernel 4.0 and later are supported from the linux-4 tree.
Linux kernel 5.0 and later are supported from the linux-5 tree.
Linux kernel 6.0 and later are supported from the linux-6 tree.

Extract the kernel source and go to the extracted directory.
In the operations below, "$VERSION" should be replaced with appropriate kernel version. For example "6.1" if using Linux kernel 6.1.1, "2.6.27" if using Linux kernel 2.6.27.62.
Also, there are several patches which can be applied to distributor's latest kernels. For example "3.10-centos-7" if using CentOS 7's latest kernel:

$ wget https://sourceforge.net/projects/tomoyo/files/caitsith-patch/0.2/caitsith-patch-0.2-20250415.tar.gz
$ wget https://sourceforge.net/projects/tomoyo/files/caitsith-patch/0.2/caitsith-patch-0.2-20250415.tar.gz.asc
$ wget https://tomoyo.sourceforge.net/kumaneko-key
$ gpg --import kumaneko-key
$ gpg caitsith-patch-0.2-20250415.tar.gz.asc
$ tar -zxf caitsith-patch-0.2-20250415.tar.gz
$ sed -i -e 's/CCSECURITY/CAITSITH/g' -e 's/ccsecurity/caitsith/g' -e 's/ccs_domain_info/cs_domain_info/g' -e 's/ccs_flags/cs_flags/g' -- patches/ccs-patch-*.diff
$ patch -sp1 < patches/ccs-patch-$VERSION.diff

2.2.3. Configure the kernel

$ make -s menuconfig

Choose the following options in "Security options" section:

"Compile as loadable kernel module" is useful when there is a file size limitation for vmlinux (e.g. embedded systems).

"Disable by default" will enable CaitSith only when "caitsith=on" is passed to the kernel boot options. If this option is not selected, "caitsith=off" will disable CaitSith.

"Do not modify 'struct task_struct' in order to keep KABI" will manage "struct task_struct" variables outside "struct task_struct" in order to avoid Kernel Application Binary Interface (KABI) breakage. Choose this option if wanting to patch against distributor's kernels without breaking KABI. However, since "struct caitsith_operations" must be exported to loadable kernel modules (LKMs) in order to allow them to call CaitSith's functions, build scripts may still print warning messages.

There are two types of CaitSith's policy configuration. The former is embedded into the kernel and the latter is saved as files on the filesystems (e.g. /etc/caitsith/ directory). You will need to rebuild the kernel whenever updating the former, but allows you to load policy without using userspace policy loader (e.g. /sbin/caitsith-init). The latter is loaded by executing userspace policy loader when the access control by CaitSith is about to be activated (e.g. when /sbin/init or /usr/lib/systemd/systemd starts). "Activate without calling userspace policy loader." allows you to activate access control by CaitSith as soon as the former is loaded. This option is useful when it is difficult to call policy loader (e.g. embedded systems).

"Location of userspace policy loader" is available only when "Activate without calling userspace policy loader." is not selected. This option specifies the default pathname of the userspace policy loader. You can override this setting via the "CS_loader=" kernel boot option.

"Trigger for calling userspace policy loader" is available only when "Activate without calling userspace policy loader." is not selected. This option specifies the default pathname of the activation trigger. You can override this setting via the "CS_trigger=" kernel boot option. For example, if you pass "init=/usr/lib/systemd/systemd" option, you may also want to pass "CS_trigger=/usr/lib/systemd/systemd" option.


2.2.4. Compile and install the kernel

The policy configuration which will be embedded into the kernel needs to exist as security/caitsith/policy/policy.conf . But you can proceed without creating that file because you don't have the policy configuration to embed as of this step. (You may come back here after you developed policy configuration to embed.)

Once the kernel has been configured, compile and install the kernel with the following commands:

$ make -s
$ su
# make -s modules_install install

Create initrd/initramfs if required.


2.2.5. Install the userspace tools

Make sure the dependencies described above have been installed. Compile and install the tools with the following commands. (Please use USRLIBDIR=/usr/lib or USRLIBDIR=/usr/lib32 if needed):

$ wget https://sourceforge.net/projects/tomoyo/files/caitsith-tools/0.2/caitsith-tools-0.2-20241111.tar.gz
$ wget https://sourceforge.net/projects/tomoyo/files/caitsith-tools/0.2/caitsith-tools-0.2-20241111.tar.gz.asc
$ gpg caitsith-tools-0.2-20241111.tar.gz.asc
$ tar -zxf caitsith-tools-0.2-20241111.tar.gz
$ cd caitsith-tools/
$ make -s USRLIBDIR=/usr/lib64
$ su
# make -s USRLIBDIR=/usr/lib64 install

Programs listed below are main userspace tools used for administrating CaitSith.

FYI: If your system has rpm-build package installed, you can make a tools RPM package with the following commands:

$ rpmbuild -tb caitsith-tools-0.2-20241111.tar.gz

2.2.6. Initializing configuration

Before you can make use of CaitSith, an initialization procedure must take place. This prepares the files in which policy information will be stored. All policy files are stored in the "/etc/caitsith/" directory.

Run the following command as root user to initialize. (Please use /usr/lib/caitsith/init_policy or /usr/lib32/caitsith/init_policy if needed):

# /usr/lib64/caitsith/init_policy
Creating policy directory... OK
Creating configuration directory... OK
Creating default policy... OK.
Creating module loader... OK.
Creating configuration file for caitsith-auditd ... OK.
Creating configuration file for caitsith-notifyd ... OK.

CaitSith can generate audit logs and allows you to read them via /sys/kernel/security/caitsith/audit interface. To save /sys/kernel/security/caitsith/audit automatically, start /usr/sbin/caitsith-auditd from somewhere. Default setting (specified in /etc/caitsith/tools/auditd.conf ) sends access allowed logs to /dev/null , access unmatched logs to /var/log/caitsith/unmatched.log , access denied logs to /var/log/caitsith/denied.log . (The meaning and example of allowed/unmatched/denied will be explained in Example of simple access restriction rule.)

CaitSith can ask for your decision about access requests which will be denied unless you allow them via /sys/kernel/security/caitsith/query interface. To notify immediately the occurrence of access requests which CaitSith is about to deny, start /usr/sbin/caitsith-notifyd from somewhere. Default setting (specified in /etc/caitsith/tools/notifyd.conf ) sends mails to root@localhost with subject "Notification from caitsith-notifyd" up to once per a minute.

Below example launches /usr/sbin/caitsith-auditd and /usr/sbin/caitsith-notifyd from /etc/rc.d/rc.local script:

#!/bin/bash
# THIS FILE IS ADDED FOR COMPATIBILITY PURPOSES
#
# It is highly advisable to create own systemd services or udev rules
# to run scripts during boot instead of using this file.
#
# In contrast to previous versions due to parallel execution during boot
# this script will NOT be run after all other services.
#
# Please note that you must run 'chmod +x /etc/rc.d/rc.local' to ensure
# that this script will be executed during boot.

touch /var/lock/subsys/local
/usr/sbin/caitsith-auditd
/usr/sbin/caitsith-notifyd

2.2.7. Configuring your bootloader

Edit your bootloader (e.g. GRUB) to include the kernel you have just compiled. If the "Disable by default" option was selected during kernel configuration, remember to include "caitsith=on" in the kernel boot options. Consult the documentation for your distribution and bootloader to find out how to include your CaitSith kernel.


2.2.8. Rebooting your system

Now you have finished all preparation. Reboot your system.

If everything was installed properly and the bootloader was correctly configured, the kernel should boot as normal and CaitSith should be activated:

caitsith-activated.png

Note that you won't be able to see CaitSith's messages if you are using "quiet" or "rhgb" kernel boot option because these options prevent most of kernel messages from being printed.


2.2.9. How can I disable/uninstall CaitSith?

If your system becomes unable to boot during the course of this guide or any time in the future, it may be due to policy configuration or something related to CaitSith. If this is the case, it is possible that the kernel can still be booted by disabling CaitSith. This can be done by appending "caitsith=off" to the kernel boot options.

CaitSith fortunately does not require the modification of any existing Linux binaries, libraries or applications. Thus, uninstalling CaitSith is very easy. It is simply a matter of uninstalling the kernel and userspace tools that you installed above. You can reboot with the kernel provided by your distribution and then remove the entry from your bootloader.


3. How to develop policy


3.1. Policy file structure

CaitSith's policy file consists with "Header part" and "ACL part".

3.1.1. Header part of policy file

Header part consists with below lines.

POLICY_VERSION=20120401
stat $stat_name $stat_value
quota memory policy $max_byte_for_policy
quota memory audit $max_byte_for_audit_logs
quota memory query $max_byte_for_query
quota audit[$audit_index] allowed=$max_logs_for_allowed_request denied=$max_logs_for_denied_request unmatched=$max_logs_for_unmatched_request
string_group $string_group_name $string_group_member
number_group $number_group_name $number_group_member
ip_group $ip_group_name $ip_group_member

3.1.2. ACL part of policy file

ACL part consists with 0 or more repetitions of below block.

$acl_priority acl $operation $conditions_to_filter
    audit $audit_index
    $cond_priority $decision $conditions_to_allow_or_deny

$decision lines in a block is evaluated only when the block's $acl_priority line matched.

Checking of $decision lines in a block lasts until it matches a $decision line or it reaches to the end of block.

Access requests will be denied only when "deny" line of "acl" block matched. (There are two exceptions. Regarding permission to change domains manually (i.e. acl manual_domain_transition blocks) and permission to change domains automatically (i.e. acl auto_domain_transition blocks), access requests will be granted only when "allow" line of all blocks match, in order to avoid unintended domain transition.)

$acl_priority and $cond_priority values are used for two purposes. One is for selectively deny operations using "deny" lines. For example,

10 acl read path.fsmagic=0x9FA0
    audit 0
    10 deny path="proc:/cmdline"
    20 allow

denies opening /proc/cmdline on the proc filesystem (proc filesystem's magic number is 0x9FA0) for reading while allowing opening all other files.

The other is for controlling which "transition=" and "handler=" arguments should be used when these arguments matched more than once. This will be explained in advanced usage.

3.1.3. An example policy file

Below is an example of /etc/caitsith/policy/current file on CentOS. The content of this file varies depending on environments you are using, and will be updated as you develop policy.

POLICY_VERSION=20120401

quota memory audit 16777216
quota memory query 1048576
quota audit[1] allowed=0 denied=1024 unmatched=1024

10000 acl execute
    audit 0
    10 allow path="/sbin/modprobe" transition="/sbin/modprobe"
    10 allow path="/sbin/init" transition="/sbin/init"
    10 allow path="/sbin/mingetty" transition="/sbin/mingetty"
    10 allow path="/sbin/udevd" transition="/sbin/udevd"
    10 allow path="/usr/sbin/anacron" transition="/usr/sbin/anacron"
    10 allow path="/usr/sbin/crond" transition="/usr/sbin/crond"
    10 allow path="/usr/sbin/httpd" transition="/usr/sbin/httpd"
    10 allow path="/usr/sbin/logrotate" transition="/usr/sbin/logrotate"
    10 allow path="/usr/sbin/nmbd" transition="/usr/sbin/nmbd"
    10 allow path="/usr/sbin/smbd" transition="/usr/sbin/smbd"
    10 allow path="/usr/sbin/sshd" transition="/usr/sbin/sshd"
    10 allow path="/etc/rc.d/init.d/ntpd" transition="/etc/rc.d/init.d/ntpd"
    10 allow path="/etc/rc.d/init.d/single" transition="/etc/rc.d/init.d/single"
    10 allow path="/etc/rc.d/init.d/killall" transition="/etc/rc.d/init.d/killall"
    10 allow path="/etc/rc.d/init.d/ip6tables" transition="/etc/rc.d/init.d/ip6tables"
    10 allow path="/etc/rc.d/init.d/halt" transition="/etc/rc.d/init.d/halt"
    10 allow path="/etc/rc.d/init.d/netfs" transition="/etc/rc.d/init.d/netfs"
    10 allow path="/etc/rc.d/init.d/messagebus" transition="/etc/rc.d/init.d/messagebus"
    10 allow path="/etc/rc.d/init.d/sandbox" transition="/etc/rc.d/init.d/sandbox"
    10 allow path="/etc/rc.d/init.d/rsyslog" transition="/etc/rc.d/init.d/rsyslog"
    10 allow path="/etc/rc.d/init.d/smb" transition="/etc/rc.d/init.d/smb"
    10 allow path="/etc/rc.d/init.d/sshd" transition="/etc/rc.d/init.d/sshd"
    10 allow path="/etc/rc.d/init.d/cgconfig" transition="/etc/rc.d/init.d/cgconfig"
    10 allow path="/etc/rc.d/init.d/udev-post" transition="/etc/rc.d/init.d/udev-post"
    10 allow path="/etc/rc.d/init.d/firstboot" transition="/etc/rc.d/init.d/firstboot"
    10 allow path="/etc/rc.d/init.d/ntpdate" transition="/etc/rc.d/init.d/ntpdate"
    10 allow path="/etc/rc.d/init.d/crond" transition="/etc/rc.d/init.d/crond"
    10 allow path="/etc/rc.d/init.d/restorecond" transition="/etc/rc.d/init.d/restorecond"
    10 allow path="/etc/rc.d/init.d/httpd" transition="/etc/rc.d/init.d/httpd"
    10 allow path="/etc/rc.d/init.d/rdisc" transition="/etc/rc.d/init.d/rdisc"
    10 allow path="/etc/rc.d/init.d/postfix" transition="/etc/rc.d/init.d/postfix"
    10 allow path="/etc/rc.d/init.d/saslauthd" transition="/etc/rc.d/init.d/saslauthd"
    10 allow path="/etc/rc.d/init.d/netconsole" transition="/etc/rc.d/init.d/netconsole"
    10 allow path="/etc/rc.d/init.d/network" transition="/etc/rc.d/init.d/network"
    10 allow path="/etc/rc.d/init.d/avahi-daemon" transition="/etc/rc.d/init.d/avahi-daemon"
    10 allow path="/etc/rc.d/init.d/auditd" transition="/etc/rc.d/init.d/auditd"
    10 allow path="/etc/rc.d/init.d/nmb" transition="/etc/rc.d/init.d/nmb"
    10 allow path="/etc/rc.d/init.d/iptables" transition="/etc/rc.d/init.d/iptables"
    10 allow path="/etc/rc.d/init.d/cgred" transition="/etc/rc.d/init.d/cgred"

0 acl modify_policy
    audit 1
    1 deny task.uid!=0
    1 deny task.euid!=0
    100 allow task.exe="/usr/sbin/caitsith-loadpolicy"
    100 allow task.exe="/usr/sbin/caitsith-queryd"
    10000 deny

3.2. Updating policy configuration

There are two ways to update policy configuration.

One is to use /sbin/caitsith-init which is automatically called when /sbin/init starts. /sbin/caitsith-init reads policy from /etc/caitsith/policy/current and writes to /sys/kernel/security/caitsith/policy interface. Therefore, you can update policy configuration by updating /etc/caitsith/policy/current and rebooting your system.

The other is to use /usr/sbin/caitsith-loadpolicy which is defined for loading policy after your system has booted. /usr/sbin/caitsith-loadpolicy reads policy from standard input and writes to /sys/kernel/security/caitsith/policy interface. Therefore, you can update policy configuration without updating /etc/caitsith/policy/current and rebooting your system. For example, if you want to append a "string_group mygroup1 /" line to /sys/kernel/security/caitsith/policy interface, run below command:

# echo 'string_group mygroup1 /' | /usr/sbin/caitsith-loadpolicy

If you want to delete the "string_group mygroup1 /" line from /sys/kernel/security/caitsith/policy interface, run below command:

# echo 'delete string_group mygroup1 /' | /usr/sbin/caitsith-loadpolicy

The contents in /sys/kernel/security/caitsith/policy will be lost when your system shuts down or reboots. To save /sys/kernel/security/caitsith/policy as /etc/caitsith/policy/current , run below command:

# /usr/sbin/caitsith-savepolicy

3.3. Example of simple access restriction rule

Let's experience how CaitSith restricts access using simple examples.

3.3.1. Telling CaitSith which access requests should be checked

By default, CaitSith does not deny access requests. To restrict access requests, you need to tell CaitSith which access requests should be denied.

Below rule will check access requests which open /tmp/file1 for reading.

100 acl read path="/tmp/file1"
    audit 1

Append above rule using /usr/sbin/caitsith-loadpolicy . Since /usr/sbin/caitsith-loadpolicy reads policy from standard input, you can use ^D (Ctrl-D) to indicate end of input:

# /usr/sbin/caitsith-loadpolicy
100 acl read path="/tmp/file1"
    audit 1
^D

You may use a temporary file if you worry typos.

# cat > ~/policy.tmp
100 acl read path="/tmp/file1"
    audit 1
^D
# /usr/sbin/caitsith-loadpolicy < ~/policy.tmp
# rm ~/policy.tmp

You can confirm that above rule is appended to /sys/kernel/security/caitsith/policy by reading /sys/kernel/security/caitsith/policy .

# cat /sys/kernel/security/caitsith/policy
POLICY_VERSION=20120401
stat Policy updated: 7 (Last: 2012/04/08 04:56:45)
stat Requests denied: 0
stat Memory used by policy: 6048
stat Memory used by audit: 0
stat Memory used by query: 0
quota memory audit 16777216
quota memory query 1048576
quota audit[1] allowed=0 denied=1024 unmatched=1024

10000 acl execute
    audit 0
    10 allow path="/sbin/modprobe" transition="/sbin/modprobe"
    10 allow path="/sbin/init" transition="/sbin/init"
    10 allow path="/sbin/mingetty" transition="/sbin/mingetty"
    10 allow path="/sbin/udevd" transition="/sbin/udevd"
    10 allow path="/usr/sbin/anacron" transition="/usr/sbin/anacron"
    10 allow path="/usr/sbin/crond" transition="/usr/sbin/crond"
    10 allow path="/usr/sbin/httpd" transition="/usr/sbin/httpd"
    10 allow path="/usr/sbin/logrotate" transition="/usr/sbin/logrotate"
    10 allow path="/usr/sbin/nmbd" transition="/usr/sbin/nmbd"
    10 allow path="/usr/sbin/smbd" transition="/usr/sbin/smbd"
    10 allow path="/usr/sbin/sshd" transition="/usr/sbin/sshd"
    10 allow path="/etc/rc.d/init.d/ntpd" transition="/etc/rc.d/init.d/ntpd"
    10 allow path="/etc/rc.d/init.d/single" transition="/etc/rc.d/init.d/single"
    10 allow path="/etc/rc.d/init.d/killall" transition="/etc/rc.d/init.d/killall"
    10 allow path="/etc/rc.d/init.d/ip6tables" transition="/etc/rc.d/init.d/ip6tables"
    10 allow path="/etc/rc.d/init.d/halt" transition="/etc/rc.d/init.d/halt"
    10 allow path="/etc/rc.d/init.d/netfs" transition="/etc/rc.d/init.d/netfs"
    10 allow path="/etc/rc.d/init.d/messagebus" transition="/etc/rc.d/init.d/messagebus"
    10 allow path="/etc/rc.d/init.d/sandbox" transition="/etc/rc.d/init.d/sandbox"
    10 allow path="/etc/rc.d/init.d/rsyslog" transition="/etc/rc.d/init.d/rsyslog"
    10 allow path="/etc/rc.d/init.d/smb" transition="/etc/rc.d/init.d/smb"
    10 allow path="/etc/rc.d/init.d/sshd" transition="/etc/rc.d/init.d/sshd"
    10 allow path="/etc/rc.d/init.d/cgconfig" transition="/etc/rc.d/init.d/cgconfig"
    10 allow path="/etc/rc.d/init.d/udev-post" transition="/etc/rc.d/init.d/udev-post"
    10 allow path="/etc/rc.d/init.d/firstboot" transition="/etc/rc.d/init.d/firstboot"
    10 allow path="/etc/rc.d/init.d/ntpdate" transition="/etc/rc.d/init.d/ntpdate"
    10 allow path="/etc/rc.d/init.d/crond" transition="/etc/rc.d/init.d/crond"
    10 allow path="/etc/rc.d/init.d/restorecond" transition="/etc/rc.d/init.d/restorecond"
    10 allow path="/etc/rc.d/init.d/httpd" transition="/etc/rc.d/init.d/httpd"
    10 allow path="/etc/rc.d/init.d/rdisc" transition="/etc/rc.d/init.d/rdisc"
    10 allow path="/etc/rc.d/init.d/postfix" transition="/etc/rc.d/init.d/postfix"
    10 allow path="/etc/rc.d/init.d/saslauthd" transition="/etc/rc.d/init.d/saslauthd"
    10 allow path="/etc/rc.d/init.d/netconsole" transition="/etc/rc.d/init.d/netconsole"
    10 allow path="/etc/rc.d/init.d/network" transition="/etc/rc.d/init.d/network"
    10 allow path="/etc/rc.d/init.d/avahi-daemon" transition="/etc/rc.d/init.d/avahi-daemon"
    10 allow path="/etc/rc.d/init.d/auditd" transition="/etc/rc.d/init.d/auditd"
    10 allow path="/etc/rc.d/init.d/nmb" transition="/etc/rc.d/init.d/nmb"
    10 allow path="/etc/rc.d/init.d/iptables" transition="/etc/rc.d/init.d/iptables"
    10 allow path="/etc/rc.d/init.d/cgred" transition="/etc/rc.d/init.d/cgred"

100 acl read path="/tmp/file1"
    audit 1

0 acl modify_policy
    audit 1
    1 deny task.uid!=0
    1 deny task.euid!=0
    100 allow task.exe="/usr/sbin/caitsith-loadpolicy"
    100 allow task.exe="/usr/sbin/caitsith-queryd"
    10000 deny

3.3.2. Access requests which will be implicitly allowed by CaitSith

Make sure that /usr/sbin/caitsith-auditd is running.

# pidof caitsith-auditd
3627

Now, create /tmp/file1 file.

# touch /tmp/file1

Then, open /tmp/file1 for reading.

# cat /tmp/file1

Check /var/log/caitsith/unmatched.log for access unmatched log of this access request. You will find an entry like below:

# grep /tmp/file1 /var/log/caitsith/unmatched.log
#2012/04/08 04:58:40# global-pid=3678 result=unmatched priority=100 / read path="/tmp/file1" task.pid=3678 task.ppid=3653 task.uid=0 task.gid=0 task.euid=0 task.egid=0 task.suid=0 task.sgid=0 task.fsuid=0 task.fsgid=0 task.type!=execute_handler task.exe="/bin/cat" task.domain="/usr/sbin/sshd" path.uid=0 path.gid=0 path.ino=2113451 path.major=8 path.minor=1 path.perm=0644 path.type=file path.fsmagic=0xEF53 path.parent.uid=0 path.parent.gid=0 path.parent.ino=2097153 path.parent.major=8 path.parent.minor=1 path.parent.perm=01777 path.parent.type=directory path.parent.fsmagic=0xEF53

Note the result=unmatched part of the entry. This indicates that access request was checked but matched neither "allow" nor "deny" rule.

Note the priority=100 part of the entry. This indicates that this entry was generated by rules which have 100 as priority.

Note the read path="/tmp/file1" part of the entry. This indicates that this entry was generated by access request of opening /tmp/file1 for reading.

3.3.3. Access requests which will be explicitly denied by CaitSith

Now, let's add a rule to explicitly deny this request.

100 acl read path="/tmp/file1"
    1000 deny

Append above rule using /usr/sbin/caitsith-loadpolicy :

# /usr/sbin/caitsith-loadpolicy
100 acl read path="/tmp/file1"
    1000 deny
^D

Rules that have same priority (in this rule, 100) and same operation (in this rule, read) and same condition (in this rule, path="/tmp/file1") are automatically merged. Therefore, you will find

100 acl read path="/tmp/file1"
    audit 1
    1000 deny

rather than

100 acl read path="/tmp/file1"
    audit 1

100 acl read path="/tmp/file1"
    1000 deny

when you read /sys/kernel/security/caitsith/policy .

Then, open /tmp/file1 for reading.

# cat /tmp/file1
cat: /tmp/file1: Operation not permitted

This time, access request was denied by CaitSith.

Check /var/log/caitsith/denied.log for access denied log of this access request. You will find an entry like below:

# grep /tmp/file1 /var/log/caitsith/denied.log
#2012/04/08 04:59:53# global-pid=3682 result=denied priority=100 / read path="/tmp/file1" task.pid=3682 task.ppid=3653 task.uid=0 task.gid=0 task.euid=0 task.egid=0 task.suid=0 task.sgid=0 task.fsuid=0 task.fsgid=0 task.type!=execute_handler task.exe="/bin/cat" task.domain="/usr/sbin/sshd" path.uid=0 path.gid=0 path.ino=2113451 path.major=8 path.minor=1 path.perm=0644 path.type=file path.fsmagic=0xEF53 path.parent.uid=0 path.parent.gid=0 path.parent.ino=2097153 path.parent.major=8 path.parent.minor=1 path.parent.perm=01777 path.parent.type=directory path.parent.fsmagic=0xEF53

Note the result=denied part of the entry. This indicates that access request was checked and matched "deny" rule.

If /usr/sbin/caitsith-notifyd is running, you will receive a notification mail. The content is same with access denied logs.

# mail
Heirloom Mail version 12.4 7/29/08.  Type ? for help.
"/var/spool/mail/root": 1 message 1 new
>N  1 root                  Sun Apr  8 13:59  20/1231  "Notification from caitsith-notifyd"
&
Message  1:
From root@ccsecurity.localdomain  Sun Apr  8 13:59:53 2012
Return-Path: <root@ccsecurity.localdomain>
X-Original-To: root@localhost
Delivered-To: root@localhost.localdomain
Date: Sun, 08 Apr 2012 13:59:53 +0900
To: root@localhost.localdomain
Subject: Notification from caitsith-notifyd
User-Agent: Heirloom mailx 12.4 7/29/08
Content-Type: text/plain; charset=us-ascii
From: root@caitsith.localdomain (root)
Status: R

Q0-0
#2012/04/08 04:59:53# global-pid=3682 result=denied priority=100 / read path="/tmp/file1" task.pid=3682 task.ppid=3653 task.uid=0 task.gid=0 task.euid=0 task.egid=0 task.suid=0 task.sgid=0 task.fsuid=0 task.fsgid=0 task.type!=execute_handler task.exe="/bin/cat" task.domain="/usr/sbin/sshd" path.uid=0 path.gid=0 path.ino=2113451 path.major=8 path.minor=1 path.perm=0644 path.type=file path.fsmagic=0xEF53 path.parent.uid=0 path.parent.gid=0 path.parent.ino=2097153 path.parent.major=8 path.parent.minor=1 path.parent.perm=01777 path.parent.type=directory path.parent.fsmagic=0xEF53

Now, let's remove a rule to explicitly deny this request.

100 acl read path="/tmp/file1"
    delete 1000 deny

Append above rule using /usr/sbin/caitsith-loadpolicy :

# /usr/sbin/caitsith-loadpolicy
100 acl read path="/tmp/file1"
    delete 1000 deny
^D

You will find

100 acl read path="/tmp/file1"
    audit 1

rather than

100 acl read path="/tmp/file1"
    audit 1
    1000 deny
    delete 1000 deny

when you read /sys/kernel/security/caitsith/policy .

3.3.4. Filtering audit logs

Now, open /tmp/file1 for reading.

# cat /tmp/file1

Check /var/log/caitsith/unmatched.log for access unmatched log of this access request. You will find entries like below:

# grep /tmp/file1 /var/log/caitsith/unmatched.log
#2012/04/08 04:58:40# global-pid=3678 result=unmatched priority=100 / read path="/tmp/file1" task.pid=3678 task.ppid=3653 task.uid=0 task.gid=0 task.euid=0 task.egid=0 task.suid=0 task.sgid=0 task.fsuid=0 task.fsgid=0 task.type!=execute_handler task.exe="/bin/cat" task.domain="/usr/sbin/sshd" path.uid=0 path.gid=0 path.ino=2113451 path.major=8 path.minor=1 path.perm=0644 path.type=file path.fsmagic=0xEF53 path.parent.uid=0 path.parent.gid=0 path.parent.ino=2097153 path.parent.major=8 path.parent.minor=1 path.parent.perm=01777 path.parent.type=directory path.parent.fsmagic=0xEF53
#2012/04/08 05:01:00# global-pid=3695 result=unmatched priority=100 / read path="/tmp/file1" task.pid=3695 task.ppid=3653 task.uid=0 task.gid=0 task.euid=0 task.egid=0 task.suid=0 task.sgid=0 task.fsuid=0 task.fsgid=0 task.type!=execute_handler task.exe="/bin/cat" task.domain="/usr/sbin/sshd" path.uid=0 path.gid=0 path.ino=2113451 path.major=8 path.minor=1 path.perm=0644 path.type=file path.fsmagic=0xEF53 path.parent.uid=0 path.parent.gid=0 path.parent.ino=2097153 path.parent.major=8 path.parent.minor=1 path.parent.perm=01777 path.parent.type=directory path.parent.fsmagic=0xEF53

The former entry was generated before adding explicit "deny" rule. The latter entry was generated after removing explicit "deny" rule. You might want to filter the output using tail command:

# grep /tmp/file1 /var/log/caitsith/unmatched.log | tail -n 1
#2012/04/08 05:01:00# global-pid=3695 result=unmatched priority=100 / read path="/tmp/file1" task.pid=3695 task.ppid=3653 task.uid=0 task.gid=0 task.euid=0 task.egid=0 task.suid=0 task.sgid=0 task.fsuid=0 task.fsgid=0 task.type!=execute_handler task.exe="/bin/cat" task.domain="/usr/sbin/sshd" path.uid=0 path.gid=0 path.ino=2113451 path.major=8 path.minor=1 path.perm=0644 path.type=file path.fsmagic=0xEF53 path.parent.uid=0 path.parent.gid=0 path.parent.ino=2097153 path.parent.major=8 path.parent.minor=1 path.parent.perm=01777 path.parent.type=directory path.parent.fsmagic=0xEF53

3.3.5. Access requests which will be explicitly allowed by CaitSith

Next, let's see audit logs with explicitly matching "allow" rules.

By default CaitSith does not generate audit logs with explicitly matching "allow" rules. Change policy configuration to generate such logs.

quota audit[1] allowed=1024

Append above rule using /usr/sbin/caitsith-loadpolicy :

# echo 'quota audit[1] allowed=1024' | /usr/sbin/caitsith-loadpolicy

Preferences that have same name (in this rule, audit[1]) are automatically merged. Therefore, you will find

quota audit[1] allowed=1024 denied=1024 unmatched=1024

rather than

quota audit[1] allowed=0 denied=1024 unmatched=1024
quota audit[1] allowed=1024

when you read /sys/kernel/security/caitsith/policy .

100 acl read path="/tmp/file1"
    1000 allow

Append above rule using /usr/sbin/caitsith-loadpolicy :

# /usr/sbin/caitsith-loadpolicy
100 acl read path="/tmp/file1"
    1000 allow
^D

Since audit logs with explicitly matching "allow" rules tend to grow rapidly, by default /usr/sbin/caitsith-auditd discards such logs by writing to /dev/null (specified in /etc/caitsith/tools/auditd.conf ). Therefore, temporarily stop /usr/sbin/caitsith-auditd process in order to read audit logs from /sys/kernel/security/caitsith/audit interface.

# killall -KILL caitsith-auditd

Then, open /tmp/file1 for reading.

# cat /tmp/file1

Check /sys/kernel/security/caitsith/audit for audit log of this access request. This time, you will find an entry like below:

# cat -v /sys/kernel/security/caitsith/audit
#2012/04/08 05:03:03# global-pid=3720 result=allowed priority=100 / read path="/tmp/file1" task.pid=3720 task.ppid=3653 task.uid=0 task.gid=0 task.euid=0 task.egid=0 task.suid=0 task.sgid=0 task.fsuid=0 task.fsgid=0 task.type!=execute_handler task.exe="/bin/cat" task.domain="/usr/sbin/sshd" path.uid=0 path.gid=0 path.ino=2113451 path.major=8 path.minor=1 path.perm=0644 path.type=file path.fsmagic=0xEF53 path.parent.uid=0 path.parent.gid=0 path.parent.ino=2097153 path.parent.major=8 path.parent.minor=1 path.parent.perm=01777 path.parent.type=directory path.parent.fsmagic=0xEF53
^@

Note the result=allowed part of the entry. This indicates that access request was checked and matched "allow" rule.

Restart /usr/sbin/caitsith-auditd process.

# /usr/sbin/caitsith-auditd

Also, restore the audit logs configuration:

quota audit[1] allowed=0

Append above rule using /usr/sbin/caitsith-loadpolicy :

# echo 'quota audit[1] allowed=0' | /usr/sbin/caitsith-loadpolicy

3.4. Understanding two viewpoints

CaitSith supports writing access restriction rules from two viewpoints. One is from the point of view of "subject" (a resource which requests access on object). The other is from the point of view of "object" (a resource which subject requests access).

The advantage of the former approach is that the rules clearly explains and restricts what each subject is allowed to access which object. This approach is powerful when you can afford identifying all possible subjects and defining the rules for each subject. But the disadvantage is that it is difficult to identify all possible subjects and define the rules for each subject. Therefore, in reality, this approach tends to restrict only specific subjects. If one of subjects which is not restricted by this approach is cracked or misbehaved, nothing can protect objects you want to protect.

The advantage of the latter approach is that the rules clearly explains and restricts what object might be accessed by which subject. This approach is powerful when you can afford identifying objects you want to protect and defining rules for each object. This approach can compensate for the disadvantage of the former approach because this approach can restrict access even when it is difficult to identify all possible subjects and define the rules for each possible subject.

3.4.1. Writing access restriction rules from the point of view of "subject".

Below entry is an example of restricting programs which can be executed from /usr/sbin/httpd program.

0 acl execute task.exe="/usr/sbin/httpd"
    audit 1
    1 allow path="/var/www/cgi-bin/counter.cgi"
    100 deny

The 0 acl execute task.exe="/usr/sbin/httpd" line means check rules for executing programs from /usr/sbin/httpd program. Since task.exe="/usr/sbin/httpd" is specified in this line, this line tells CaitSith check rules for executing programs only if current thread's program name is /usr/sbin/httpd.

The line 1 allow path="/var/www/cgi-bin/counter.cgi" means that allow if the pathname of the program to execute is /var/www/cgi-bin/counter.cgi . This line tells CaitSith "allow execution of /var/www/cgi-bin/counter.cgi".

The line 100 deny means deny unconditionally. This tells CaitSith "unconditionally deny execution of programs".

Since the line starting with 1 allow has higher priority than the line starting with 100 deny, CaitSith will allow execution of /var/www/cgi-bin/counter.cgi .

To summarize this rule, /usr/sbin/httpd can execute only /var/www/cgi-bin/counter.cgi .

The line audit 1 means that use audit rules defined in the quota audit[1] line. This line tells CaitSith generate audit logs up to entries defined in the quota audit[1] line. The default configuration generated by executing /usr/lib64/caitsith/init_policy command is

quota audit[1] allowed=0 denied=1024 unmatched=1024

which means do not generate audit logs if matched an "allow" line and generate audit logs up to 1024 entries if matched a "deny" line and generate audit logs up to 1024 lines if matched neither an "allow" line nor a "deny" line. Though, since the block starting with 0 acl execute task.exe="/usr/sbin/httpd" is terminated with explicit 100 deny line, this block shall match either an "allow" line or a "deny" line.

3.4.2. Writing access restriction rules from the point of view of "object".

Below entry is default configuration generated by executing /usr/lib64/caitsith/init_policy command.

0 acl modify_policy
    audit 1
    1 deny task.uid!=0
    1 deny task.euid!=0
    100 allow task.exe="/usr/sbin/caitsith-loadpolicy"
    100 allow task.exe="/usr/sbin/caitsith-queryd"
    10000 deny

The 0 acl modify_policy line means check rules for modifying policy configuration via /sys/kernel/security/caitsith/policy interface. Since no additional conditions are specified in this line, this line tells CaitSith unconditionally check rules for modifying policy configuration via /sys/kernel/security/caitsith/policy interface.

The line 1 deny task.uid!=0 means that deny if current thread's user ID is not 0. This line tells CaitSith "deny modification of policy configuration via /sys/kernel/security/caitsith/policy interface if current thread's user ID is not 0".

The line 1 deny task.euid!=0 means that deny if current thread's effective user ID is not 0. This line tells CaitSith "deny modification of policy configuration via /sys/kernel/security/caitsith/policy interface if current thread's effective user ID is not 0".

Note the difference between

    1 deny task.uid!=0
    1 deny task.euid!=0

and

    1 deny task.uid!=0 task.euid!=0

. The former conditions tell CaitSith "deny if current thread's user ID is not 0 or current thread's effective user ID is not 0", while the latter conditions tell CaitSith "deny if current thread's user ID is not 0 and current thread's effective user ID is not 0".

The line 100 allow task.exe="/usr/sbin/caitsith-loadpolicy" means that allow if current thread's program name is /usr/sbin/caitsith-loadpolicy . This tells CaitSith finish evaluation of this block starting with the 0 acl modify_policy line if current thread's program name is /usr/sbin/caitsith-loadpolicy . If there are more blocks, CaitSith will evaluate them. If there are no more blocks, CaitSith will allow modifying policy configuration via /sys/kernel/security/caitsith/policy interface.

The line 100 allow task.exe="/usr/sbin/caitsith-queryd" means that allow if current thread's program name is /usr/sbin/caitsith-queryd . This tells CaitSith finish evaluation of this block starting with the 0 acl modify_policy line if current thread's program name is /usr/sbin/caitsith-queryd . The usage of /usr/sbin/caitsith-queryd will be explained later.

The line 10000 deny means deny unconditionally. This tells CaitSith "unconditionally deny modification of policy configuration via /sys/kernel/security/caitsith/policy interface".

Since lines starting with 1 deny have higher priority than lines starting with 100 allow, CaitSith will deny modifying policy configuration via /sys/kernel/security/caitsith/policy interface if current thread's user ID is not 0 or current thread's effective user ID is not 0. In other words, only root user (where current thread's user ID and effective user ID are both 0) can modify policy configuration via /sys/kernel/security/caitsith/policy interface.

Since lines starting with 100 allow have higher priority than a line starting with 10000 deny, CaitSith will allow modifying policy configuration via /sys/kernel/security/caitsith/policy interface if current thread's program name is /usr/sbin/caitsith-loadpolicy or current thread's program name is /usr/sbin/caitsith-queryd . In other words, other programs such as /bin/sh , /bin/echo , /bin/cat are not allowed to modify policy configuration via /sys/kernel/security/caitsith/policy interface.

To summarize this rule, only /usr/sbin/caitsith-loadpolicy or /usr/sbin/caitsith-queryd command running as root user can modify policy configuration via /sys/kernel/security/caitsith/policy interface.

Note the difference between

0 acl execute task.exe="/usr/sbin/httpd"
    audit 1
    1 allow path="/var/www/cgi-bin/counter.cgi"
    100 deny

and

0 acl execute path="/var/www/cgi-bin/counter.cgi"
    audit 1
    1 allow task.exe="/usr/sbin/httpd"
    100 deny

. The former means "/usr/sbin/httpd can execute only /var/www/cgi-bin/counter.cgi", while the latter means "only /usr/sbin/httpd can execute /var/www/cgi-bin/counter.cgi".

CaitSith supports restricting other arguments such as command line arguments and environment variables. Syntax for restricting other arguments will be explained later.

3.4.3. Writing access restriction rules from the point of view of both "subject" and "object".

It is possible to write access restriction rules like

0 acl execute task.exe="/usr/sbin/httpd" path="/var/www/cgi-bin/counter.cgi"
    audit 1
    1 allow task.uid!=0
    100 deny

and

0 acl execute task.uid!=0
    audit 1
    1 allow task.exe="/usr/sbin/httpd" path="/var/www/cgi-bin/counter.cgi"
    100 deny

. The former means "/usr/sbin/httpd is allowed to execute /var/www/cgi-bin/counter.cgi only if current thread's user ID is not 0", while the latter means "only execution of /var/www/cgi-bin/counter.cgi from /usr/sbin/httpd is allowed if current thread's user ID is not 0".

Also, it is possible to write access restriction rules like

0 acl execute
    audit 1
    1 allow task.exe="/usr/sbin/httpd" path="/var/www/cgi-bin/counter.cgi"
    100 deny

which means "any execute requests other than execution of /var/www/cgi-bin/counter.cgi from /usr/sbin/httpd are denied" (DO NOT TRY THIS EXAMPLE, or you will no longer be able to run any commands).


3.5. Steps for writing access restriction rules

An example of steps for writing access restriction rules using pathnames is shown here.

Step 1: Determine resource to restrict access.

Below example restricts opening /etc/shadow for reading.

100 acl read path="/etc/shadow"
    audit 1

Step 2: Gather logs of accessing resources.

As you operate the system with above example, access unmatched logs are generated and spooled in /sys/kernel/security/caitsith/audit interface when access request of opening /etc/shadow for reading happens. If /usr/sbin/caitsith-auditd is running, access unmatched logs will be moved to /var/log/caitsith/unmatched.log .

#2012/03/02 08:11:51# global-pid=2826 result=unmatched priority=100 / read path="/etc/shadow" task.pid=2826 task.ppid=2814 task.uid=0 task.gid=0 task.euid=0 task.egid=0 task.suid=0 task.sgid=0 task.fsuid=0 task.fsgid=0 task.type!=execute_handler task.exe="/usr/bin/passwd" task.domain="/usr/sbin/sshd" path.uid=0 path.gid=42 path.ino=33708 path.major=8 path.minor=1 path.perm=0640 path.type=file path.fsmagic=0xEF53 path.parent.uid=0 path.parent.gid=0 path.parent.ino=32769 path.parent.major=8 path.parent.minor=1 path.parent.perm=0755 path.parent.type=directory path.parent.fsmagic=0xEF53

Step 3: Decide whether to allow or deny.

Examine the log and decide whether to allow this access request or not. To allow this request, add an allow line. Below example allows this request to /usr/bin/passwd program.

100 acl read path="/etc/shadow"
    audit 1
    100 allow task.exe="/usr/bin/passwd"

Step 4: Gather again logs of accessing resources.

Operate the system again. For example, /usr/sbin/sshd program and /bin/cat program have requested opening /etc/shadow for reading.

#2012/03/02 08:13:06# global-pid=2831 result=unmatched priority=100 / read path="/etc/shadow" task.pid=2831 task.ppid=2691 task.uid=0 task.gid=0 task.euid=0 task.egid=0 task.suid=0 task.sgid=0 task.fsuid=0 task.fsgid=0 task.type!=execute_handler task.exe="/usr/sbin/sshd" task.domain="/usr/sbin/sshd" path.uid=0 path.gid=42 path.ino=33716 path.major=8 path.minor=1 path.perm=0640 path.type=file path.fsmagic=0xEF53 path.parent.uid=0 path.parent.gid=0 path.parent.ino=32769 path.parent.major=8 path.parent.minor=1 path.parent.perm=0755 path.parent.type=directory path.parent.fsmagic=0xEF53
#2012/03/02 08:13:12# global-pid=2837 result=unmatched priority=100 / read path="/etc/shadow" task.pid=2837 task.ppid=2833 task.uid=0 task.gid=0 task.euid=0 task.egid=0 task.suid=0 task.sgid=0 task.fsuid=0 task.fsgid=0 task.type!=execute_handler task.exe="/bin/cat" task.domain="/usr/sbin/sshd" path.uid=0 path.gid=42 path.ino=33716 path.major=8 path.minor=1 path.perm=0640 path.type=file path.fsmagic=0xEF53 path.parent.uid=0 path.parent.gid=0 path.parent.ino=32769 path.parent.major=8 path.parent.minor=1 path.parent.perm=0755 path.parent.type=directory path.parent.fsmagic=0xEF53

Step 5: Decide again whether to allow or deny.

Add an allow line with /usr/sbin/sshd program in order to allow access by /usr/sbin/sshd program. Also, add a deny line with /bin/cat program in order to deny access by /bin/cat program. Give higher priority (i.e. smaller $cond_priority value) to deny line than allow line so that deny lines are checked before allow lines are checked.

100 acl read path="/etc/shadow"
    audit 1
    10 deny task.exe="/bin/cat"
    100 allow task.exe="/usr/bin/passwd"
    100 allow task.exe="/usr/sbin/sshd"

From now on, attempt to read /etc/shadow using /bin/cat should be denied and access denied logs should be generated. If /usr/sbin/caitsith-auditd is running, access denied logs will be moved to /var/log/caitsith/denied.log .

#2012/03/02 08:14:38# global-pid=2842 result=denied priority=100 / read path="/etc/shadow" task.pid=2842 task.ppid=2833 task.uid=0 task.gid=0 task.euid=0 task.egid=0 task.suid=0 task.sgid=0 task.fsuid=0 task.fsgid=0 task.type!=execute_handler task.exe="/bin/cat" task.domain="/usr/sbin/sshd" path.uid=0 path.gid=42 path.ino=33716 path.major=8 path.minor=1 path.perm=0640 path.type=file path.fsmagic=0xEF53 path.parent.uid=0 path.parent.gid=0 path.parent.ino=32769 path.parent.major=8 path.parent.minor=1 path.parent.perm=0755 path.parent.type=directory path.parent.fsmagic=0xEF53

Step 6: Finish up a rule.

After you have finished enumerating all allow lines and deny lines, add a deny line with lowest priority (i.e. largest $cond_priority value within this block).

100 acl read path="/etc/shadow"
    audit 1
    10 deny task.exe="/bin/cat"
    100 allow task.exe="/usr/bin/passwd"
    100 allow task.exe="/usr/sbin/sshd"
    10000 deny

A rule for restricting /etc/shadow for opening is now completed. Please do not copy and paste this example, for there must be other programs which need to open /etc/shadow for reading.


3.6. Restricting access in various ways

The rule demonstrated in 3.5. Steps for writing access restriction rules alone cannot prevent diverted accesses such as creating a hard link of /etc/shadow . CaitSith supports various variables for writing access restriction rules. If the resource to protect has characteristic attribute, it is recommended to utilize such attributes. (The full list of available variables/attributes will be explained in 4. List of conditions.)

On several distributions, /etc/shadow is owned by shadow group. In that case, this rule can be modified to below. (Below example assumes that shadow group's group ID is 42.)

100 acl read path.gid=42
    audit 1
    10 deny task.exe="/bin/cat"
    100 allow task.exe="/usr/bin/passwd"
    100 allow task.exe="/usr/sbin/sshd"
    10000 deny

On several distributions, /etc/shadow is owned by root user and root group and has DAC permissions 0400. In that case, you might want to use a rule like below. (You should check whether there are other files with such attributes.)

100 acl read path.uid=0 path.gid=0 path.perm=0400
    audit 1
    10 deny task.exe="/bin/cat"
    100 allow task.exe="/usr/bin/passwd"
    100 allow task.exe="/usr/sbin/sshd"
    10000 deny

It is recommended to restrict other operations such as mount, link and rename. For example, a rule to deny creation of hard links which is not owned by the user would look like below. (Note that the variable which refers source pathname of link operation is "old_path" rather than "path" because the operation is "link".)

100 acl link old_path.uid!=task.uid
    audit 1
    100 deny

If you can split files into different filesystems or different partitions, you might be able to utilize more variables. For example, rules for denying creation of hard links on tmpfs filesystem (tmpfs filesystem's magic number is 0x01021994) would look like below.

100 acl link old_path.fsmagic=0x01021994
    audit 1
    10 deny

Splitting into different partitions and defining rules based on partition's attributes will help preventing diverted access via creating hard links, for hard links cannot be created across partitions. Separating /home partition from / partition will be useful when protecting resources in /home partition.


4. List of conditions


4.1. Using string arguments in conditions

Arguments such as file's pathnames and command line arguments and environment variables are handled as string argument.

4.1.1. About string argument representation rule

All ASCII printable characters other than \ character (i.e. from 33 to 91 and from 93 to 126) are represented as is.

All other characters (i.e. from 0 to 32, 92 and from 127 to 255) are represented using \ooo style octal form.

Lower 4 bits
Upper 4 bits

0x0

0x1

0x2

0x3

0x4

0x5

0x6

0x7

0x8

0x9

0xA

0xB

0xC

0xD

0xE

0xF

0x0

\000

\001

\002

\003

\004

\005

\006

\007

\010

\011

\012

\013

\014

\015

\016

\017

0x1

\020

\021

\022

\023

\024

\025

\026

\027

\030

\031

\032

\033

\034

\035

\036

\037

0x2

\040

!

"

#

$

%

&

'

(

)

*

+

,

-

.

/

0x3

0

1

2

3

4

5

6

7

8

9

:

;

<

=

>

?

0x4

@

A

B

C

D

E

F

G

H

I

J

K

L

M

N

O

0x5

P

Q

R

S

T

U

V

W

X

Y

Z

[

\134

]

^

_

0x6

`

a

b

c

d

e

f

g

h

i

j

k

l

m

n

o

0x7

p

q

r

s

t

u

v

w

x

y

z

{

|

}

~

\177

0x8

\200

\201

\202

\203

\204

\205

\206

\207

\210

\211

\212

\213

\214

\215

\216

\217

0x9

\220

\221

\222

\223

\224

\225

\226

\227

\230

\231

\232

\233

\234

\235

\236

\237

0xA

\240

\241

\242

\243

\244

\245

\246

\247

\250

\251

\252

\253

\254

\255

\256

\257

0xB

\260

\261

\262

\263

\264

\265

\266

\267

\270

\271

\272

\273

\274

\275

\276

\277

0xC

\300

\301

\302

\303

\304

\305

\306

\307

\310

\311

\312

\313

\314

\315

\316

\317

0xD

\320

\321

\322

\323

\324

\325

\326

\327

\330

\331

\332

\333

\334

\335

\336

\337

0xE

\340

\341

\342

\343

\344

\345

\346

\347

\350

\351

\352

\353

\354

\355

\356

\357

0xF

\360

\361

\362

\363

\364

\365

\366

\367

\370

\371

\372

\373

\374

\375

\376

\377

Some examples are shown below.

/bin/sh
/home/demo/Documents\040and\040Settings

4.1.2. Grouping string arguments using wildcard expressions.

It is possible to use wildcards listed below in order to match string patterns.

Wildcard

Pattern match

Examples

\*

0 or more repetitions of characters other than "/"

/var/log/samba/\*

\@

0 or more repetitions of characters other than "/" or "."

/var/www/html/\@.html

\?

1 byte character other than "/"

/tmp/mail.\?\?\?\?\?\?

\$

1 or more repetitions of decimal digits

/proc/\$/cmdline

\+

1 decimal digit

/var/tmp/my_work.\+

\X

1 or more repetitions of hexadecimal digits

/var/tmp/my-work.\X

\x

1 hexadecimal digit

/tmp/my-work.\x

\A

1 or more repetitions of alphabet characters

/var/log/my-work/\$-\A-\$.log

\a

1 alphabet character

/home/users/\a/\*/public_html/\*.html

\-

Pathname subtraction operator (negative match)

/\*\-proc\-sys

This will match /\* except "/proc" and "/sys".

/\{dir\}/

Recursive directory matching operator.

Matches "/" and 1 or more repetitions of "dir/".

/var/www/html/\{\*\}/\*.html

This will match all *.html files in subdirectories under /var/www/html/ directory. Note that /var/www/html/\*.html will not match.

/\(dir\)/

Recursive directory matching operator.

Matches "/" and 0 or more repetitions of "dir/".

/var/www/html/\(\*\)/\*.html

This will match all *.html files under /var/www/html/ directory. Note that /var/www/html/\*.html will match.

4.1.3. Grouping string arguments using string_group keyword.

It is possible to define groups of string arguments using string_group keyword followed by $string_group_name and $string_group_member.

string_group TMPDIR /tmp
string_group TMPDIR /tmp/\(\*\)/\*

4.1.4. Example of conditions that use string arguments.

When string argument is specified in condition part, it is quoted by " character in order to clarify that the argument is a string argument rather than name of variable.

Conditions exampleValue of variable "path"Comparison result
path="/tmp/\*" /Does not match
/tmpDoes not match
/tmp/Matches
/tmp/rt6bh84tMatches
/tmp/349gy08t/y8024fgfDoes not match
path!="/tmp/\*" /Matches
/tmpMatches
/tmp/Does not match
/tmp/rt6bh84tDoes not match
/tmp/349gy08t/y8024fgfMatches

When string_group argument is specified in condition part, it is prefixed by @ character in order to clarify that the argument is a string_group argument rather than name of variable.

Conditions exampleValue of variable "path"Values in TMPDIR groupComparison result
path=@TMPDIR //tmp
/tmp/\(\*\)/\*
Does not match
/tmpMatches
/tmp/rt6bh84tMatches
/tmp/349gy08t/y8024fgfMatches
path!=@TMPDIR //tmp
/tmp/\(\*\)/\*
Matches
/tmpDoes not match
/tmp/rt6bh84tDoes not match
/tmp/349gy08t/y8024fgfDoes not match

List of name of variables which reference string data is explained later.


4.2. Using numeric arguments in conditions

Arguments such as user ID and process ID are handled as numeric argument.

4.2.1. About numeric argument representation rule

Decimal form, octal form and hexadecimal form are supported. Octal form is prefixed with 0 and Hexadecimal form is prefixed with 0x. For example, 010 in octal form is equivalent with 8 in decimal form, 0x10 in hexadecimal form is equivalent with 16 in decimal form.

Since numeric data is handled using C language's "unsigned long" type, minimal value is 0 and maximal value is 0xFFFFFFFF (for 32 bit environments) or 0xFFFFFFFFFFFFFFFF (for 64 bit environments).

It is possible to specify numeric data ranges in $min_value-$max_value form. If specifying in range, $min_value has to be smaller or equals to $max_value. For example, 0-100 is valid but 100-0 is invalid.

Some examples are shown below.

0
100
0xFFFF
0777
500-1000
0x0-0xFFFFFFFF
00-07777

4.2.2. Grouping numeric arguments using number_group keyword.

It is possible to define groups of numeric arguments using number_group keyword followed by $number_group_name and $number_group_member.

number_group ID_GROUP 100
number_group ID_GROUP 200-500

4.2.3. Example of conditions that use numeric arguments.

Comparison with numeric value is defined as below.

Conditions exampleValue of variable "task.uid"Comparison result
task.uid=0 0Matches
100Does not match
500Does not match
task.uid!=0 0Does not match
100Matches
500Matches

Comparison with numeric value range is defined as below.

Conditions exampleValue of variable "task.gid"Comparison result
task.gid=0-100 0Matches
100Matches
500Does not match
task.gid!=0-1000Does not match
100Does not match
500Matches

It is possible to compare one variable which references numeric value with another variable which references numeric value.

Conditions exampleValue of variable "task.uid"Value of variable "task.gid"Comparison result
task.uid=task.gid 00Matches
0100Does not match
1000Does not match
100100Matches
task.uid!=task.gid 00Does not match
0100Matches
1000Matches
100100Does not match

When number_group argument is specified in condition part, it is prefixed by @ character in order to clarify that the argument is a number_group argument rather than name of variable.

Conditions exampleValue of variable "task.uid"Values in ID_GROUP groupComparison result
task.uid=@ID_GROUP 0100
200-500
Does not match
100Matches
500Matches
1000Does not match
task.uid!=@ID_GROUP 0100
200-500
Matches
100Does not match
500Does not match
1000Matches

List of name of variables which reference numeric data is explained later.


4.3. Using process's information in conditions

By using current thread's attributes as part of conditions, you can write complicated access restriction rules.

4.3.1. About available variables

Below variables are available for referring current thread's attributes.

Variable's nameComparison methodMeaning
task.uidNumericCurrent thread's user ID
task.gidNumericCurrent thread's group ID
task.euidNumericCurrent thread's effective user ID
task.egidNumericCurrent thread's effective group ID
task.suidNumericCurrent thread's saved user ID
task.sgidNumericCurrent thread's saved group ID
task.fsuidNumericCurrent thread's filesystem user ID
task.fsgidNumericCurrent thread's filesystem group ID
task.pidNumericCurrent thread's process ID
task.ppidNumericProcess ID of current thread's parent process
task.exeStringCurrent thread's program name (the content of /proc/self/exe)
task.domainStringCurrent thread's domainname (the content of /sys/kernel/security/caitsith/self_domain)
task.typeLiteralMatches execute_handler if running as an execute handler, does not match execute_handler otherwise

Details of task.domain is explained in 6.1. Controlling domain transition and task.type is explained in 6.2. Using execute handler.


4.4. Using IP address arguments in conditions

Any operation which handles IPv4/IPv6 network address can check IP address.

4.4.1. About IP address argument representation rule

It is possible to handle IPv4 address and IPv6 address. IPv4 address (32 bit) is represented using dot separated decimal form. and IPv6 address (128 bit) is represented using forms defined in RFC 2373.

It is possible to specify IP address ranges in $min_address-$max_address form. If specifying in range, $min_address has to be smaller or equals to $max_address. For example, 1.2.3.4-5.6.7.8 is valid but 5.6.7.8-1.2.3.4 is invalid.

Some examples are shown below.

127.0.0.1
10.0.0.0-10.255.255.255
::1
fd00::-fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff

4.4.2. Grouping IP address arguments using ip_group keyword.

It is possible to define groups of IP address arguments using ip_group keyword followed by $ip_group_name and $ip_group_member.

ip_group PRIVATE_ADDRESS 10.0.0.0-10.255.255.255
ip_group PRIVATE_ADDRESS 172.16.0.0-172.31.255.255
ip_group PRIVATE_ADDRESS 192.168.0.0-192.168.255.255
ip_group PRIVATE_ADDRESS fd00::-fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff

4.4.3. Example of conditions that use IP address arguments.

Comparison with IP address value is defined as below. Note that comparison between an IPv4 address and an IPv6 address does not match.

Conditions exampleValue of variable "ip"Comparison result
ip=127.0.0.1127.0.0.1Matches
0.0.0.0Does not match
::1Does not match
::ffff:127.0.0.1Does not match
ip!=127.0.0.1127.0.0.1Does not match
0.0.0.0Matches
::1Does not match
::ffff:127.0.0.1Does not match
ip=::1127.0.0.1Does not match
0.0.0.0Does not match
::1Matches
::ffff:127.0.0.1Does not match
ip!=::1127.0.0.1Does not match
0.0.0.0Does not match
::1Does not match
::ffff:127.0.0.1Matches

Comparison with IP address range is defined as below.

Conditions exampleValue of variable "ip"Comparison result
ip=127.0.0.0-127.255.255.255 127.0.0.1Matches
10.0.0.1Does not match
::ffff:127.0.0.1Does not match
ip!=127.0.0.0-127.255.255.255 127.0.0.1Does not match
10.0.0.1Matches
::ffff:127.0.0.1Does not match
ip=::-::1::ffff:127.0.0.1Does not match
127.0.0.1Does not match
::1Matches
ip!=::-::1::ffff:127.0.0.1Matches
127.0.0.1Does not match
::1Does not match

When ip_group argument is specified in condition part, it is prefixed by @ character in order to clarify that the argument is an ip_group argument rather than name of variable.

Conditions exampleValue of variable "ip"Values in PRIVATE_ADDRESS groupComparison result
ip=@PRIVATE_ADDRESS 127.0.0.110.0.0.0-10.255.255.255
172.16.0.0-172.31.255.255
192.168.0.0-192.168.255.255
fd00::-fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
Does not match
10.0.0.1Matches
192.168.0.1Matches
::ffff:172.16.0.1Does not match
fd01::Matches
ip!=@PRIVATE_ADDRESS127.0.0.110.0.0.0-10.255.255.255
172.16.0.0-172.31.255.255
192.168.0.0-192.168.255.255
fd00::-fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
Matches
10.0.0.1Does not match
::ffff:192.168.0.1Matches
::ffff:127.0.0.1Matches
fd01::Does not match

List of operations which handles IP address is explained later.


4.5. Using command line arguments in conditions

It is possible to check command line arguments (a.k.a. argv[]) when checking permissions for program execution.

Conditions exampleComparison methodMeaning
argv[0]="true"Stringargv[0] matches "true"
argv[0]!="false"Stringargv[0] does not match "false"
argv[1]=@ARGV1_GROUPSStringargv[0] matches one of strings in string_group ARGV1_GROUPS group
argv[1]!=@ARGV1_GROUPSStringargv[0] matches none of strings in string_group ARGV1_GROUPS group

Applications can pass a string data up to 32 * PAGE_SIZE bytes to each argv[]. But due to difficulty of allocating contiguous memory in the kernel, only up to 4085 bytes can be checked using variable "argv[$index]". If you want to check strictly, please consider using handler= argument of "allow " lines in "acl execute" block.


4.6. Using environment variable arguments in conditions

It is possible to check environment variables (a.k.a. envp[]) when checking permissions for program execution.

Conditions exampleComparison methodMeaning
envp["PATH"]="/"StringEnvironment variable PATH is defined and its value is "/"
envp["PATH"]!="/"StringEither
    Environment variable PATH is not defined
or
    Environment variable PATH is defined but its value is not "/"
envp["PATH"]=@ENV_PATH_VALUESStringEnvironment variable PATH is defined and its value matches one of strings in string_group ENVP_PATH_VALUES group
envp["PATH"]!=@ENV_PATH_VALUESStringEither
    Environment variable PATH is not defined
or
    Environment variable PATH is defined but its value matches none of strings in string_group ENVP_PATH_VALUES group
envp["PATH"]=NULLNoneEnvironment variable PATH is not defined
envp["PATH"]!=NULLNoneEnvironment variable PATH is defined

Applications can pass a string data up to 32 * PAGE_SIZE bytes to each envp[]. But due to difficulty of allocating contiguous memory in the kernel, only up to 4085 bytes can be checked using variable "envp["$name"]". If you want to check strictly, please consider using handler= argument of "allow " lines in "acl execute" block.


4.7. Using file's DAC permissions in conditions

When checking permissions for file related operations, it is possible to check its DAC permissions if the file already exists as of permission check. Below table assumes that the variable name for referencing the requested pathname is "path".

Value of DAC permissions can be referenced using variable "path.perm", and its value is between 0 and 07777. Although it is possible to do normal numeric comparison, below constants are provided in order to make it easier to compare whether specific bit is set or not.

ConstantValue ranges that match
setuidValues where bitwise AND between path.perm and 04000 are 04000. (i.e. 04000-07777)
setgidValues where bitwise AND between path.perm and 02000 are 02000. (i.e. 02000-03777 06000-07777)
stickyValues where bitwise AND between path.perm and 01000 are 01000. (i.e. 01000-01777 03000-03777 05000-05777 07000-07777)
owner_readValues where bitwise AND between path.perm and 00400 are 00400. (e.g. 00400-00777 01400-01777 02400-02777)
owner_writeValues where bitwise AND between path.perm and 00200 are 00200. (e.g. 00200-00377 00600-00777 01200-01377)
owner_executeValues where bitwise AND between path.perm and 00100 are 00100. (e.g. 00100-00177 00300-00377 00500-00577)
group_readValues where bitwise AND between path.perm and 00040 are 00040. (e.g. 00040-00077 00140-00177 00240-00277)
group_writeValues where bitwise AND between path.perm and 00020 are 00020. (e.g. 00020-00037 00060-00077 00120-00137)
group_executeValues where bitwise AND between path.perm and 00010 are 00010. (e.g. 00010-00017 00030-00037 00050-00057)
others_readValues where bitwise AND between path.perm and 00004 are 00004. (e.g. 00004-00007 00014-00017 00024-00027)
others_writeValues where bitwise AND between path.perm and 00002 are 00002. (e.g. 00002-00003 00006-00007 00012-00013)
others_executeValues where bitwise AND between path.perm and 00001 are 00001. (e.g. 00001 00003 00005 00007 00011 00013)

Below are some examples that use constants.

Conditions examplePermissions of file referenced by variable "path"Comparison result
path.perm=setuid04755Matches
path.perm!=setuid04755Does not match
path.perm=setuid path.perm=setgid path.perm=sticky0755Does not match
path.perm!=setuid path.perm!=setgid path.perm!=sticky0755Matches

4.8. Using handle file's type in conditions

When checking permissions for file related operations, it is possible to check its type if the file already exists as of permission check. Below table assumes that the variable name for referencing the requested pathname is "path".

Type of a file can be referenced using variable "path.type", and its value takes one of "file", "directory", "socket", "fifo", "block", "char", "symlink".

Possible conditionsType of file referenced by variable "path"Comparison result
path.type=fileRegular fileMatches
path.type!=fileOther than regular fileMatches
path.type=directoryDirectoryMatches
path.type!=directoryOther than directoryMatches
path.type=socketUnix domain socketMatches
path.type!=socketOther than Unix domain socketMatches
path.type=fifoFIFOMatches
path.type!=fifoOther than FIFOMatches
path.type=blockBlock device fileMatches
path.type!=blockOther than block device fileMatches
path.type=charCharacter device fileMatches
path.type!=charOther than character device fileMatches
path.type=symlinkSymbolic linkMatches
path.type!=symlinkOther than symbolic linkMatches

4.9. Using file's attributes in conditions

When checking permissions for file related operations, it is possible to check its attributes if the file already exists as of permission check. Below table assumes that the variable name for referencing the requested pathname is "path".

Variable's nameComparison methodMeaning
path.uidNumericOwner ID
path.gidNumericGroup ID
path.inoNumerici-node number on the filesystem
path.majorNumericDevice major number on the filesystem
path.minorNumericDevice minor number on the filesystem
path.permPermissionDAC permissions
path.typeFile's typeType of the file
path.dev_majorNumericDevice major number of the file if path.type=block or path.type=char
path.dev_minorNumericDevice minor number of the file if path.type=block or path.type=char
path.fsmagicNumericMagic number of filesystem

When checking permissions for file related operations, it is possible to also check its parent directory's attributes. Below table assumes that the variable name for referencing the requested pathname is "path".

Variable's nameComparison methodMeaning
path.parent.uidNumericOwner ID
path.parent.gidNumericGroup ID
path.parent.inoNumerici-node number on the filesystem
path.parent.majorNumericDevice major number on the filesystem
path.parent.minorNumericDevice minor number on the filesystem
path.parent.permPermissionDAC permissions
path.parent.fsmagicNumericMagic number of filesystem

It does not make sense to use path.parent.type path.parent.dev_major path.parent.dev_minor because path.parent is always a directory.

If path refers a mount point (root of directory entry tree within that partition), path.parent refers the same path rather than referring mount point's parent.


5. List of syntaxes


5.1. execute

5.1.1. Description

Execute a program

5.1.2. Available variables

pathRequested program's pathname
path.$attributeAttributes of an object referenced by variable "path"
path.parent.$attributeParent directory's attributes
execRequested program's pathname, but maybe a symbolic link
exec.$attributeAttributes of an object referenced by variable "exec"
exec.parent.$attributeParent directory's attributes
argcNumber of command line arguments passed to this request
envcNumber of environment variables arguments
argv[$index]$index'th (0 <= $index < argc) value of command line arguments
envp["$name"]Value of environment variable named $name
task.$attributeCurrent thread's attributes
handlerPathname of a wrapper program for preprocessing (note that this assignment is optional and valid to only "allow" lines)
transitionNew domainname to transit to if operation was successful (note that this assignment is optional and valid to only "allow" lines)

5.1.3. Examples

5.1.4. Related man pages

execve(2)

5.1.5. Availability

Checking handler argument is available only when built with CONFIG_CAITSITH_EXECUTE_HANDLER=y.

Checking other arguments are always available.


5.2. read

5.2.1. Description

Open a pathname for reading

5.2.2. Available variables

pathRequested pathname
path.$attributeAttributes of an object referenced by variable "path"
path.parent.$attributeParent directory's attributes
task.$attributeCurrent thread's attributes

5.2.3. Examples

5.2.4. Related man pages

open(2)

5.2.5. Availability

Checking directory's permission is available only when built with CONFIG_CAITSITH_READDIR=y.

Checking non-directory's permission is always available.


5.3. write

5.3.1. Description

Open a pathname for writing

5.3.2. Available variables

pathRequested pathname
path.$attributeAttributes of an object referenced by variable "path"
path.parent.$attributeParent directory's attributes
task.$attributeCurrent thread's attributes

5.3.3. Examples

5.3.4. Related man pages

open(2)

5.3.5. Availability

Always available.


5.4. append

5.4.1. Description

Open a pathname for appending

5.4.2. Available variables

pathRequested pathname
path.$attributeAttributes of an object referenced by variable "path"
path.parent.$attributeParent directory's attributes
task.$attributeCurrent thread's attributes

5.4.3. Examples

5.4.4. Related man pages

open(2)

5.4.5. Availability

Always available.


5.5. create

5.5.1. Description

Create a regular file

5.5.2. Available variables

pathRequested pathname
permDAC permissions of a new object referenced by variable "path"
path.parent.$attributeParent directory's attributes
task.$attributeCurrent thread's attributes

5.5.3. Examples

5.5.4. Related man pages

open(2), mknod(2)

5.5.5. Availability

Always available.


5.6. unlink

5.6.1. Description

Delete a non-directory pathname

5.6.2. Available variables

pathRequested pathname
path.$attributeAttributes of an object referenced by variable "path"
path.parent.$attributeParent directory's attributes
task.$attributeCurrent thread's attributes

5.6.3. Examples

5.6.4. Related man pages

unlink(2)

5.6.5. Availability

Always available.


5.7. getattr

5.7.1. Description

Get attributes of a pathname

5.7.2. Available variables

pathRequested pathname
path.$attributeAttributes of an object referenced by variable "path"
path.parent.$attributeParent directory's attributes
task.$attributeCurrent thread's attributes

5.7.3. Examples

5.7.4. Related man pages

stat(2)

5.7.5. Availability

Available only when built with CONFIG_CAITSITH_GETATTR=y.


5.8. mkdir

5.8.1. Description

Create a directory

5.8.2. Available variables

pathRequested pathname
permDAC permissions of a new object referenced by variable "path"
path.parent.$attributeParent directory's attributes
task.$attributeCurrent thread's attributes

5.8.3. Examples

5.8.4. Related man pages

mkdir(2)

5.8.5. Availability

Always available.


5.9. rmdir

5.9.1. Description

Delete a directory pathname

5.9.2. Available variables

pathRequested pathname
path.$attributeAttributes of an object referenced by variable "path"
path.parent.$attributeParent directory's attributes
task.$attributeCurrent thread's attributes

5.9.3. Examples

5.9.4. Related man pages

rmdir(2)

5.9.5. Availability

Always available.


5.10. mkfifo

5.10.1. Description

Create a FIFO

5.10.2. Available variables

pathRequested pathname
permDAC permissions of a new object referenced by variable "path"
path.parent.$attributeParent directory's attributes
task.$attributeCurrent thread's attributes

5.10.3. Examples

5.10.4. Related man pages

mknod(2)

5.10.5. Availability

Always available.


5.11. mksock

5.11.1. Description

Create a Unix domain socket

5.11.2. Available variables

pathRequested pathname
permDAC permissions of a new object referenced by variable "path"
path.parent.$attributeParent directory's attributes
task.$attributeCurrent thread's attributes

5.11.3. Examples

5.11.4. Related man pages

mknod(2)

5.11.5. Availability

Always available.


5.12. truncate

5.12.1. Description

Truncate a regular file

5.12.2. Available variables

pathRequested pathname
path.$attributeAttributes of an object referenced by variable "path"
path.parent.$attributeParent directory's attributes
task.$attributeCurrent thread's attributes

5.12.3. Examples

5.12.4. Related man pages

open(2), truncate(2)

5.12.5. Availability

Always available.


5.13. symlink

5.13.1. Description

Create a symbolic link

5.13.2. Available variables

pathRequested pathname
targetSymbolic link's content
path.parent.$attributeParent directory's attributes
task.$attributeCurrent thread's attributes

5.13.3. Examples

5.13.4. Related man pages

symlink(2)

5.13.5. Availability

Always available.


5.14. mkblock

5.14.1. Description

Create a block device file

5.14.2. Available variables

pathRequested pathname
permDAC permissions of a new object referenced by variable "path"
dev_majorMajor device number of a new object referenced by variable "path"
dev_minorMinor device number of a new object referenced by variable "path"
path.parent.$attributeParent directory's attributes
task.$attributeCurrent thread's attributes

5.14.3. Examples

5.14.4. Related man pages

mknod(2)

5.14.5. Availability

Always available.


5.15. mkchar

5.15.1. Description

Create a character device file

5.15.2. Available variables

pathRequested pathname
permDAC permissions of a new object referenced by variable "path"
dev_majorMajor device number of a new object referenced by variable "path"
dev_minorMinor device number of a new object referenced by variable "path"
path.parent.$attributeParent directory's attributes
task.$attributeCurrent thread's attributes

5.15.3. Examples

5.15.4. Related man pages

mknod(2)

5.15.5. Availability

Always available.


5.16. link

5.16.1. Description

Create a link

5.16.2. Available variables

old_pathLink source's pathname
new_pathLink target's pathname
old_path.$attributeAttributes of an object referenced by variable "old_path"
old_path.parent.$attributeParent directory's attributes
new_path.parent.$attributeParent directory's attributes
task.$attributeCurrent thread's attributes

5.16.3. Examples

5.16.4. Related man pages

link(2)

5.16.5. Availability

Always available.


5.17. rename

5.17.1. Description

Rename a pathname

5.17.2. Available variables

old_pathOld pathname
new_pathNew pathname
old_path.$attributeAttributes of an object referenced by variable "old_path"
old_path.parent.$attributeParent directory's attributes
new_path.$attributeAttributes of an existing object referenced by variable "new_path" (note that these attributes are available only when "new_path" already exists)
new_path.parent.$attributeParent directory's attributes
task.$attributeCurrent thread's attributes

5.17.3. Examples

5.17.4. Related man pages

rename(2)

5.17.5. Availability

Always available.


5.18. chmod

5.18.1. Description

Change DAC's permission

5.18.2. Available variables

pathRequested pathname
permNew DAC permissions of an object referenced by variable "path"
path.$attributeAttributes of an object referenced by variable "path"
path.parent.$attributeParent directory's attributes
task.$attributeCurrent thread's attributes

5.18.3. Examples

5.18.4. Related man pages

chmod(2)

5.18.5. Availability

Always available.


5.19. chown

5.19.1. Description

Change DAC's owner ID

5.19.2. Available variables

pathRequested pathname
uidNew DAC owner ID of an object referenced by variable "path"
path.$attributeAttributes of an object referenced by variable "path"
path.parent.$attributeParent directory's attributes
task.$attributeCurrent thread's attributes

5.19.3. Examples

5.19.4. Related man pages

chown(2)

5.19.5. Availability

Always available.


5.20. chgrp

5.20.1. Description

Change DAC's group ID

5.20.2. Available variables

pathRequested pathname
gidNew DAC group ID of an object referenced by variable "path"
path.$attributeAttributes of an object referenced by variable "path"
path.parent.$attributeParent directory's attributes
task.$attributeCurrent thread's attributes

5.20.3. Examples

5.20.4. Related man pages

chown(2)

5.20.5. Availability

Always available.


5.21. ioctl

5.21.1. Description

Use ioctl request

5.21.2. Available variables

pathRequested pathname
cmdCommand number for ioctl request
path.$attributeAttributes of an object referenced by variable "path"
path.parent.$attributeParent directory's attributes
task.$attributeCurrent thread's attributes

5.21.3. Examples

5.21.4. Related man pages

ioctl(2)

5.21.5. Availability

Always available.


5.22. chroot

5.22.1. Description

Change root directory

5.22.2. Available variables

pathRequested pathname
path.$attributeAttributes of an object referenced by variable "path"
path.parent.$attributeParent directory's attributes
task.$attributeCurrent thread's attributes

5.22.3. Examples

5.22.4. Related man pages

chroot(2)

5.22.5. Availability

Always available.


5.23. mount

5.23.1. Description

Mount a filesystem

5.23.2. Available variables

sourceSource name if filesystem name is one of "--bind", "--move" or a filesystem that requires device file. Unavailable otherwise.
targetMount point or target name
fstypeFilesystem name, determined by below order.
  1. "--remount" if mount flags contains MS_REMOUNT flag
  2. "--bind" if mount flags contains MS_BIND flag
  3. "--make-shared" if mount flags contains MS_SHARED flag
  4. "--make-private" if mount flags contains MS_PRIVATE flag
  5. "--make-slave" if mount flags contains MS_SLAVE flag
  6. "--make-unbindable" if mount flags contains MS_UNBINDABLE flag
  7. "--move" if mount flags contains MS_MOVE flag
  8. name of filesystem
flagsMount flags
dataMount options not in mount flags argument (e.g. "errors=remount-ro"). This variable is not available to filesystems that require binary mount options (e.g."nfs", "coda", "ncpfs"). Also, this variable is available only if filesystem type is either "--remount" or name of filesystem.
source.$attributeAttributes of an object referenced by variable "source" when variable "source" references a valid pathname
source.parent.$attributeAttributes of parent directory of an object referenced by variable "source" when variable "source" references a valid pathname
target.$attributeAttributes of an object referenced by variable "target"
target.parent.$attributeAttributes of parent directory of an object referenced by variable "target"
task.$attributeCurrent thread's attributes

5.23.3. Examples

5.23.4. Related man pages

mount(2)

5.23.5. Availability

Always available.


5.24. unmount

5.24.1. Description

Unmount a filesystem

5.24.2. Available variables

pathRequested pathname
flagsUnmount flags
path.$attributeAttributes of an object referenced by variable "path"
path.parent.$attributeParent directory's attributes
task.$attributeCurrent thread's attributes

5.24.3. Examples

5.24.4. Related man pages

umount(2)

5.24.5. Availability

Always available.


5.25. pivot_root

5.25.1. Description

Exchange root directory

5.25.2. Available variables

new_rootNew root directory
put_oldLocation to place old root directory
new_root.$attributeAttributes of an object referenced by variable "new_root"
new_root.parent.$attributeAttributes of parent directory of an object referenced by variable "new_root"
put_old.$attributeAttributes of an object referenced by variable "put_old"
put_old.parent.$attributeAttributes of parent directory of an object referenced by variable "put_old"
task.$attributeCurrent thread's attributes

5.25.3. Examples

5.25.4. Related man pages

pivot_root(2)

5.25.5. Availability

Always available.


5.26. inet_stream_bind

5.26.1. Description

Binding PF_INET/PF_INET6+SOCK_STREAM socket

5.26.2. Available variables

ipIPv4 or IPv6 address
portPort number
task.$attributeCurrent thread's attributes
transitionNew domainname to transit to if conditions are met (note that this assignment is valid to only "allow" lines)

5.26.3. Examples

5.26.4. Related man pages

bind(2), ip(7), ipv6(7)

5.26.5. Availability

Available only when built with CONFIG_CAITSITH_NETWORK=y.


5.27. inet_stream_listen

5.27.1. Description

Listening PF_INET/PF_INET6+SOCK_STREAM socket

5.27.2. Available variables

ipIPv4 or IPv6 address
portPort number
task.$attributeCurrent thread's attributes
transitionNew domainname to transit to if conditions are met (note that this assignment is valid to only "allow" lines)

5.27.3. Examples

5.27.4. Related man pages

listen(2), ip(7), ipv6(7)

5.27.5. Availability

Available only when built with CONFIG_CAITSITH_NETWORK=y.


5.28. inet_stream_connect

5.28.1. Description

Connecting PF_INET/PF_INET6+SOCK_STREAM socket

5.28.2. Available variables

ipIPv4 or IPv6 address
portPort number
task.$attributeCurrent thread's attributes
transitionNew domainname to transit to if conditions are met (note that this assignment is valid to only "allow" lines)

5.28.3. Examples

5.28.4. Related man pages

connect(2), ip(7), ipv6(7)

5.28.5. Availability

Available only when built with CONFIG_CAITSITH_NETWORK=y.


5.29. inet_stream_accept

5.29.1. Description

Accepting PF_INET/PF_INET6+SOCK_STREAM socket

5.29.2. Available variables

ipIPv4 or IPv6 address
portPort number
task.$attributeCurrent thread's attributes
transitionNew domainname to transit to if conditions are met (note that this assignment is valid to only "allow" lines)

5.29.3. Examples

5.29.4. Related man pages

accept(2), ip(7), ipv6(7)

5.29.5. Availability

Available only when built with CONFIG_CAITSITH_NETWORK=y.


5.30. inet_dgram_bind

5.30.1. Description

Binding PF_INET/PF_INET6+SOCK_DGRAM socket

5.30.2. Available variables

ipIPv4 or IPv6 address
portPort number
task.$attributeCurrent thread's attributes
transitionNew domainname to transit to if conditions are met (note that this assignment is valid to only "allow" lines)

5.30.3. Examples

5.30.4. Related man pages

bind(2), ip(7), ipv6(7)

5.30.5. Availability

Available only when built with CONFIG_CAITSITH_NETWORK=y.


5.31. inet_dgram_send

5.31.1. Description

Sending AF_INET/AF_INET6 datagrams

5.31.2. Available variables

ipIPv4 or IPv6 address
portPort number
task.$attributeCurrent thread's attributes
transitionNew domainname to transit to if conditions are met (note that this assignment is valid to only "allow" lines)

5.31.3. Examples

5.31.4. Related man pages

sendmsg(2), ip(7), ipv6(7)

5.31.5. Availability

Available only when built with CONFIG_CAITSITH_NETWORK=y.


5.32. inet_dgram_recv

5.32.1. Description

Receiving AF_INET/AF_INET6 datagrams

5.32.2. Available variables

ipIPv4 or IPv6 address
portPort number
task.$attributeCurrent thread's attributes
transitionNew domainname to transit to if conditions are met (note that this assignment is valid to only "allow" lines)

5.32.3. Examples

5.32.4. Related man pages

recvmsg(2), ip(7), ipv6(7)

5.32.5. Availability

Available only when built with CONFIG_CAITSITH_NETWORK_RECVMSG=y.


5.33. inet_raw_bind

5.33.1. Description

Binding PF_INET/PF_INET6+SOCK_RAW socket

5.33.2. Available variables

ipIPv4 or IPv6 address
protoProtocol number
task.$attributeCurrent thread's attributes
transitionNew domainname to transit to if conditions are met (note that this assignment is valid to only "allow" lines)

5.33.3. Examples

5.33.4. Related man pages

bind(2), raw(7)

5.33.5. Availability

Available only when built with CONFIG_CAITSITH_NETWORK=y.


5.34. inet_raw_send

5.34.1. Description

Sending AF_INET/AF_INET6 packets

5.34.2. Available variables

ipIPv4 or IPv6 address
protoProtocol number
task.$attributeCurrent thread's attributes
transitionNew domainname to transit to if conditions are met (note that this assignment is valid to only "allow" lines)

5.34.3. Examples

5.34.4. Related man pages

sendmsg(2), raw(7)

5.34.5. Availability

Available only when built with CONFIG_CAITSITH_NETWORK=y.


5.35. inet_raw_recv

5.35.1. Description

Receiving AF_INET/AF_INET6 packets

5.35.2. Available variables

ipIPv4 or IPv6 address
protoProtocol number
task.$attributeCurrent thread's attributes
transitionNew domainname to transit to if conditions are met (note that this assignment is valid to only "allow" lines)

5.35.3. Examples

5.35.4. Related man pages

recvmsg(2), raw(7)

5.35.5. Availability

Available only when built with CONFIG_CAITSITH_NETWORK_RECVMSG=y.


5.36. unix_stream_bind

5.36.1. Description

Binding PF_UNIX+SOCK_STREAM socket

5.36.2. Available variables

addrUnix domain socket address
task.$attributeCurrent thread's attributes
transitionNew domainname to transit to if conditions are met (note that this assignment is valid to only "allow" lines)

5.36.3. Examples

5.36.4. Related man pages

bind(2), unix(7)

5.36.5. Availability

Available only when built with CONFIG_CAITSITH_NETWORK=y.


5.37. unix_stream_listen

5.37.1. Description

Listening PF_UNIX+SOCK_STREAM socket

5.37.2. Available variables

addrUnix domain socket address
task.$attributeCurrent thread's attributes
transitionNew domainname to transit to if conditions are met (note that this assignment is valid to only "allow" lines)

5.37.3. Examples

5.37.4. Related man pages

listen(2), unix(7)

5.37.5. Availability

Available only when built with CONFIG_CAITSITH_NETWORK=y.


5.38. unix_stream_connect

5.38.1. Description

Connecting PF_UNIX+SOCK_STREAM socket

5.38.2. Available variables

addrUnix domain socket address
task.$attributeCurrent thread's attributes
transitionNew domainname to transit to if conditions are met (note that this assignment is valid to only "allow" lines)

5.38.3. Examples

5.38.4. Related man pages

connect(2), unix(7)

5.38.5. Availability

Available only when built with CONFIG_CAITSITH_NETWORK=y.


5.39. unix_stream_accept

5.39.1. Description

Accepting PF_UNIX+SOCK_STREAM socket

5.39.2. Available variables

addrUnix domain socket address
task.$attributeCurrent thread's attributes
transitionNew domainname to transit to if conditions are met (note that this assignment is valid to only "allow" lines)

5.39.3. Examples

5.39.4. Related man pages

accept(2), unix(7)

5.39.5. Availability

Available only when built with CONFIG_CAITSITH_NETWORK=y.


5.40. unix_dgram_bind

5.40.1. Description

Binding PF_UNIX+SOCK_DGRAM socket

5.40.2. Available variables

addrUnix domain socket address
task.$attributeCurrent thread's attributes
transitionNew domainname to transit to if conditions are met (note that this assignment is valid to only "allow" lines)

5.40.3. Examples

5.40.4. Related man pages

bind(2), unix(7)

5.40.5. Availability

Available only when built with CONFIG_CAITSITH_NETWORK=y.


5.41. unix_dgram_send

5.41.1. Description

Sending AF_UNIX datagrams

5.41.2. Available variables

addrUnix domain socket address
task.$attributeCurrent thread's attributes
transitionNew domainname to transit to if conditions are met (note that this assignment is valid to only "allow" lines)

5.41.3. Examples

5.41.4. Related man pages

sendmsg(2), unix(7)

5.41.5. Availability

Available only when built with CONFIG_CAITSITH_NETWORK=y.


5.42. unix_dgram_recv

5.42.1. Description

Receiving AF_UNIX datagrams

5.42.2. Available variables

addrUnix domain socket address
task.$attributeCurrent thread's attributes
transitionNew domainname to transit to if conditions are met (note that this assignment is valid to only "allow" lines)

5.42.3. Examples

5.42.4. Related man pages

recvmsg(2), unix(7)

5.42.5. Availability

Available only when built with CONFIG_CAITSITH_NETWORK_RECVMSG=y.


5.43. unix_seqpacket_bind

5.43.1. Description

Binding PF_UNIX+SOCK_SEQPACKET socket

5.43.2. Available variables

addrUnix domain socket address
task.$attributeCurrent thread's attributes
transitionNew domainname to transit to if conditions are met (note that this assignment is valid to only "allow" lines)

5.43.3. Examples

5.43.4. Related man pages

bind(2), unix(7)

5.43.5. Availability

Available only when built with CONFIG_CAITSITH_NETWORK=y.


5.44. unix_seqpacket_listen

5.44.1. Description

Listening PF_UNIX+SOCK_SEQPACKET socket

5.44.2. Available variables

addrUnix domain socket address
task.$attributeCurrent thread's attributes
transitionNew domainname to transit to if conditions are met (note that this assignment is valid to only "allow" lines)

5.44.3. Examples

5.44.4. Related man pages

listen(2), unix(7)

5.44.5. Availability

Available only when built with CONFIG_CAITSITH_NETWORK=y.


5.45. unix_seqpacket_connect

5.45.1. Description

Connecting PF_UNIX+SOCK_SEQPACKET socket

5.45.2. Available variables

addrUnix domain socket address
task.$attributeCurrent thread's attributes
transitionNew domainname to transit to if conditions are met (note that this assignment is valid to only "allow" lines)

5.45.3. Examples

5.45.4. Related man pages

connect(2), unix(7)

5.45.5. Availability

Available only when built with CONFIG_CAITSITH_NETWORK=y.


5.46. unix_seqpacket_accept

5.46.1. Description

Accepting PF_UNIX+SOCK_SEQPACKET socket

5.46.2. Available variables

addrUnix domain socket address
task.$attributeCurrent thread's attributes
transitionNew domainname to transit to if conditions are met (note that this assignment is valid to only "allow" lines)

5.46.3. Examples

5.46.4. Related man pages

accept(2), unix(7)

5.46.5. Availability

Available only when built with CONFIG_CAITSITH_NETWORK=y.


5.47. ptrace

5.47.1. Description

Call ptrace() system call

5.47.2. Available variables

cmdCommand number
domainTarget process's domainname
task.$attributeCurrent thread's attributes

5.47.3. Examples

5.47.4. Related man pages

ptrace(2)

5.47.5. Availability

Available only when built with CONFIG_CAITSITH_PTRACE=y.


5.48. signal

5.48.1. Description

Send signals

5.48.2. Available variables

sigSignal number
task.$attributeCurrent thread's attributes

5.48.3. Examples

5.48.4. Related man pages

kill(2), tkill(2), tgkill(2), rt_sigqueueinfo(2), rt_tgsigqueueinfo(2)

5.48.5. Availability

Available only when built with CONFIG_CAITSITH_SIGNAL=y.


5.49. environ

5.49.1. Description

Receive environment variables upon program execution

5.49.2. Available variables

nameEnvironment variable's name
valueEnvironment variable's value
pathRequested program's pathname
path.$attributeAttributes of an object referenced by variable "path"
path.parent.$attributeParent directory's attributes
execRequested program's pathname, but maybe a symbolic link
exec.$attributeAttributes of an object referenced by variable "exec"
exec.parent.$attributeParent directory's attributes
argcNumber of command line arguments passed to this request
envcNumber of environment variables arguments
argv[$index]$index'th (0 <= $index < argc) value of command line arguments
envp["$name"]Value of environment variable named $name
task.$attributeCurrent thread's attributes

5.49.3. Examples

5.49.4. Related man pages

execve(2)

5.49.5. Availability

Available only when built with CONFIG_CAITSITH_ENVIRON=y.


5.50. modify_policy

5.50.1. Description

Modify policy configuration

5.50.2. Available variables

task.$attributeCurrent thread's attributes

5.50.3. Examples

5.50.4. Related man pages

none

5.50.5. Availability

Always available.


5.51. use_netlink_socket

5.51.1. Description

Create PF_NETLINK socket

5.51.2. Available variables

task.$attributeCurrent thread's attributes

5.51.3. Examples

5.51.4. Related man pages

socket(2), netlink(7)

5.51.5. Availability

Available only when built with CONFIG_CAITSITH_CAPABILITY=y.


5.52. use_packet_socket

5.52.1. Description

Create PF_PACKET socket

5.52.2. Available variables

task.$attributeCurrent thread's attributes

5.52.3. Examples

5.52.4. Related man pages

socket(2), packet(7)

5.52.5. Availability

Available only when built with CONFIG_CAITSITH_CAPABILITY=y.


5.53. use_reboot

5.53.1. Description

Call reboot() system call

5.53.2. Available variables

task.$attributeCurrent thread's attributes

5.53.3. Examples

5.53.4. Related man pages

reboot(2)

5.53.5. Availability

Available only when built with CONFIG_CAITSITH_CAPABILITY=y.


5.54. use_vhangup

5.54.1. Description

Call vhangup() system call

5.54.2. Available variables

task.$attributeCurrent thread's attributes

5.54.3. Examples

5.54.4. Related man pages

vhangup(2)

5.54.5. Availability

Available only when built with CONFIG_CAITSITH_CAPABILITY=y.


5.55. set_time

5.55.1. Description

Set system's time

5.55.2. Available variables

task.$attributeCurrent thread's attributes

5.55.3. Examples

5.55.4. Related man pages

stime(2), settimeofday(2), adjtimex(2)

5.55.5. Availability

Available only when built with CONFIG_CAITSITH_CAPABILITY=y.


5.56. set_priority

5.56.1. Description

Change process's priority

5.56.2. Available variables

task.$attributeCurrent thread's attributes

5.56.3. Examples

5.56.4. Related man pages

nice(2), setpriority(2)

5.56.5. Availability

Available only when built with CONFIG_CAITSITH_CAPABILITY=y.


5.57. set_hostname

5.57.1. Description

Set host's name

5.57.2. Available variables

task.$attributeCurrent thread's attributes

5.57.3. Examples

5.57.4. Related man pages

sethostname(2), setdomainname(2)

5.57.5. Availability

Available only when built with CONFIG_CAITSITH_CAPABILITY=y.


5.58. use_kernel_module

5.58.1. Description

Load or unload kernel modules

5.58.2. Available variables

task.$attributeCurrent thread's attributes

5.58.3. Examples

5.58.4. Related man pages

init_module(2), delete_module(2)

5.58.5. Availability

Available only when built with CONFIG_CAITSITH_CAPABILITY=y.


5.59. use_new_kernel

5.59.1. Description

Load a new kernel

5.59.2. Available variables

task.$attributeCurrent thread's attributes

5.59.3. Examples

5.59.4. Related man pages

kexec_load(2)

5.59.5. Availability

Available only when built with CONFIG_CAITSITH_CAPABILITY=y.


5.60. manual_domain_transition

5.60.1. Description

Change domains by writing to /sys/kernel/security/caitsith/self_domain

5.60.2. Available variables

domainDomainname to allow transition to
task.$attributeCurrent thread's attributes

5.60.3. Examples

5.60.4. Related man pages

none

5.60.5. Availability

Available only when built with CONFIG_CAITSITH_MANUAL_DOMAIN_TRANSITION=y.


5.61. auto_domain_transition

5.61.1. Description

Change domains automatically upon conditions are met

5.61.2. Available variables

task.$attributeCurrent thread's attributes
transitionNew domainname to transit to if conditions are met (note that this assignment is mandatory and valid to only "allow" lines)

5.61.3. Examples

5.61.4. Related man pages

none

5.61.5. Availability

Available only when built with CONFIG_CAITSITH_AUTO_DOMAIN_TRANSITION=y.


6. Advanced usage

Below are some hints for utilizing CaitSith more powerfully.


6.1. Controlling domain transition

Domains can be used instead of program's pathnames for grouping purpose. For example,

100 acl read path="/etc/shadow"
    audit 1
    10 deny task.exe="/bin/cat"
    100 allow task.exe="/usr/bin/passwd"
    100 allow task.exe="/usr/sbin/sshd"
    10000 deny

can be written like below if you manage domains appropriately.

100 acl read path="/etc/shadow"
    audit 1
    100 allow task.domain="passwd"
    100 allow task.domain="sshd"
    10000 deny

You can control domain transition in the acl execute blocks.

The priority controls which "transition=" argument should be used when this argument matched more than once. In the example below, 2 "acl execute" blocks with 5 transition= arguments are defined. (Note that conditional expressions such as path.uid=task.uid and path.uid!=task.uid are simplified as conditions$X for the purpose of illustration.)

10 acl execute conditions1
    audit 0
    10 allow conditions2 transition="domainname1"
    20 allow conditions3
    20 allow conditions4 transition="domainname2"

20 acl execute conditions5
    audit 0
    10 allow conditions6 transition="domainname3"
    20 allow conditions7 transition=NULL
    20 allow conditions8 transition="domainname4"

Domain transition is determined from the first matching transition= argument of allow lines, and keeps current domain if none of matching transition= argument was found. In other words,


6.2. Using execute handler

Although variables for inspecting command line arguments and environment variables are available, sometimes it is too complicated to check them. Also, sometimes you may want to do some preprocessing operations before starting specific programs.

You can apply execute handler in the acl execute blocks.

The priority controls which "handler=" argument should be used when this argument matched more than once. In the example below, 2 "acl execute" blocks with 5 handler= arguments are defined. (Note that conditional expressions such as path.uid=task.uid and path.uid!=task.uid are simplified as conditions$X for the purpose of illustration.)

10 acl execute conditions1
    audit 0
    10 allow conditions2 handler="/path/to/handler1"
    20 allow conditions3
    20 allow conditions4 handler="/path/to/handler2"

20 acl execute conditions5
    audit 0
    10 allow conditions6 handler="/path/to/handler3"
    20 allow conditions7 handler=NULL
    20 allow conditions8 handler="/path/to/handler4"

Execute handler is determined from the first matching handler= argument of allow lines, and does not use it if none of matching handler= argument was found. In other words,

Please see usr_lib_caitsith/audit-exec-param.c included in the caitsith-tools-0.2-20241111.tar.gz as an example of using execute handler program.


Return to index.