Info: Version 1.8.x is available.

Japanese Page

Last modified: $Date: 2024-03-30 11:25:00 +0000 (Sat, 30 Mar 2024) $

Phase 5: Restricting your system's behavior.

This page describes how to use TOMOYO Linux's enforcing mode and how to handle policy violations which arises in enforcing mode.


Step 1: Enabling enforcing mode

After you came to think you have done everything, run the policy editor and change the profile number to 3.

Run the policy editor. Choose target domains and press 's' key and enter '3' and press 'Enter' key.

editpolicy-httpd-set-profile3.png

Now the profile number of the /usr/sbin/httpd and descendant has changed to 3.

editpolicy-httpd-profile3.png

Press '@' key to switch to process list. Verify that /usr/sbin/httpd processes and descendant are assigned profile number 3.

editpolicy-httpd-process3.png

And now, /usr/sbin/httpd processes and descendant are protected by MAC, for the profile 3 was configured for enforcing mode.

editpolicy-profile-list-enforcing.png

Press 'q' key to quit the policy editor.

Let's try an operation which is permitted by policy.

operation-permitted.png

The operation was successfully completed, for sending mail is permitted by policy.

Let's try an operation which is not permitted by policy.

unix-penguin.png

The operation was rejected. (Seemingly, it looks like it was successfully completed. But actually, the execution of /bin/cat was rejected as you can see warning message by /bin/mail that the input was empty.)

unix-penguin-rejected.png

If the profile is configured as "PREFERENCE::enforcing={ verbose=yes }" (this is default), the "ERROR:" messages will be printed to the console when policy violation occurs.

enforcing-error.png

If you have configured audit logs at Phase 2: Initializing TOMOYO Linux., you can pick up rejected requests from audit logs using "grep".

[root@tomoyo ~]# grep -A 3 -F 'profile=3 mode=enforcing' /var/log/tomoyo/reject_log.conf
#2010-01-12 16:19:17# profile=3 mode=enforcing (global-pid=4836) task={ pid=4836 ppid=4835 uid=48 gid=48 euid=48 egid=48 suid=48 sgid=48 fsuid=48 fsgid=48 state[0]=0 state[1]=0 state[2]=0 type!=execute_handler } path1={ uid=0 gid=0 ino=917520 major=8 minor=1 perm=0755 type=file } path1.parent={ uid=0 gid=0 ino=917505 perm=0755 } exec={ realpath="/bin/cat" argc=2 envc=7 argv[]={ "cat" "/etc/passwd" } envp[]={ "TERM=linux" "PATH=/sbin:/usr/sbin:/bin:/usr/bin" "_=/bin/cat" "PWD=/usr/share/horde/admin" "LANG=en_US.UTF-8" "SHLVL=3" "LANGUAGE=en_US.UTF-8" } }
<kernel> /usr/sbin/httpd /bin/sh
allow_execute /bin/cat

--
#2010-01-12 16:19:17# profile=3 mode=enforcing (global-pid=4836) task={ pid=4836 ppid=4835 uid=48 gid=48 euid=48 egid=48 suid=48 sgid=48 fsuid=48 fsgid=48 state[0]=0 state[1]=0 state[2]=0 type!=execute_handler } path1={ uid=0 gid=0 ino=917520 major=8 minor=1 perm=0755 type=file } path1.parent={ uid=0 gid=0 ino=917505 perm=0755 }
<kernel> /usr/sbin/httpd /bin/sh
allow_read /bin/cat

The first log reports that execution of /bin/cat was requested by /bin/sh which was invoked by /usr/sbin/httpd , and the command line argument was "cat /etc/passwd". As its first line has "mode=enforcing", this request was rejected.

The second log reports that opening /bin/cat for reading requested by /bin/sh which was invoked by /usr/sbin/httpd was rejected. This is because that /bin/sh tries to open the requested program for reading when that program was not executed.

If you have configured notification daemon at Phase 2: Initializing TOMOYO Linux., you will receive mails sent by "ccs-notifyd" program. The content of mail is identical to the audit logs, except that it has serial numbers in the header.

[root@tomoyo ~]# mail
Mail version 8.1 6/6/93. Type ? for help.
"/var/spool/mail/root": 1 message 1 unread
>U 1 root@localhost.local Tue Jan 12 16:19 18/1234
&
Message 1:
From root@localhost.localdomain Tue Jan 12 16:19:17 2010
Date: Tue, 12 Jan 2010 16:19:17 +0900
From: root <root@localhost.localdomain>
To: root@localhost.localdomain

Q0-0
#2010-01-12 16:19:17# profile=3 mode=enforcing (global-pid=4836) task={ pid=4836 ppid=4835 uid=48 gid=48 euid=48 egid=48 suid=48 sgid=48 fsuid=48 fsgid=48 state[0]=0 state[1]=0 state[2]=0 type!=execute_handler } path1={ uid=0 gid=0 ino=917520 major=8 minor=1 perm=0755 type=file } path1.parent={ uid=0 gid=0 ino=917505 perm=0755 } exec={ realpath="/bin/cat" argc=2 envc=7 argv[]={ "cat" "/etc/passwd" } envp[]={ "TERM=linux" "PATH=/sbin:/usr/sbin:/bin:/usr/bin" "_=/bin/cat" "PWD=/usr/share/horde/admin" "LANG=en_US.UTF-8" "SHLVL=3" "LANGUAGE=en_US.UTF-8" } }
<kernel> /usr/sbin/httpd /bin/sh
allow_execute /bin/cat

If the profile is configured as "PREFERENCE::enforcing={ penalty=1 }", you can make the process which violated policy in enforcing mode sleep for 0.1 second. This feature is useful for avoiding that the CPU usage remains 100% when policy violation occurs in an infinite loop. Below video demonstrates a hijacked Samba server process is consuming CPU by repeating request that is not permitted by policy.


Step 2: Handling policy violation arising in during software updates

Since the behavior of the system is restricted by policy, you may need to update policy when you update packages.

You need to update policy in the following cases.

The ideal way to update policy is to rebuild from the scratch using learning mode. But it is not desirable to change from enforcing mode to other mode if the system has once entered in production state. Suppose MAC could support per-application enforcing mode, the MAC becomes useless if an application that is not running in enforcing mode was cracked. For example, the whole system becomes vulnerable if only HTTP server application is running in learning mode to rebuild policy for the application. So, in TOMOYO Linux, updating policy is done while the system is running in enforcing mode.

TOMOYO Linux includes tools that help administrators update policy while the system is running in enforcing mode. By using these tools, you can continue running the system without rebuilding from the scratch using learning mode if the modification is trivial. But note that these tools cannot always support every cases and the result of updated policy is not always the optimized.

Operation example

Below video demonstrates operation example.

[root@tomoyo ~]# /usr/sbin/ccs-queryd
Monitoring /proc/ccs/query and /etc/ld.so.cache . Press Ctrl-C to terminate.

#2010-01-10 12:27:10# profile=3 mode=enforcing (global-pid=4210) task={ pid=4210 ppid=4205 uid=0 gid=0 euid=0 egid=0 suid=0 sgid=0 fsuid=0 fsgid=0 state[0]=0 state[1]=0 state[2]=0 type!=execute_handler } path1={ uid=0 gid=0 ino=1766 major=0 minor=17 perm=0666 type=char dev_major=1 dev_minor=3 } path1.parent={ uid=0 gid=0 ino=962 perm=0755 }
<kernel> /etc/rc.d/init.d/sshd
allow_ioctl /dev/null 0x5401
Allow? ('Y'es/'N'o/'R'etry/'S'how policy/'A'dd to policy and retry):s
# select global-pid=4210
<kernel> /etc/rc.d/init.d/sshd
use_profile 3

allow_read /bin/bash
allow_read/write /dev/tty
allow_capability SYS_IOCTL
allow_read/write /dev/pts/\$
allow_read /usr/lib/locale/locale-archive
allow_read /etc/nsswitch.conf
allow_read /etc/passwd
allow_read /etc/rc.d/init.d/sshd
allow_read /etc/rc.d/init.d/functions
allow_execute /sbin/consoletype if exec.realpath="/sbin/consoletype" exec.argv[0]="/sbin/consoletype"
allow_read /etc/profile.d/lang.sh
allow_read /etc/sysconfig/i18n
allow_read /etc/sysconfig/init
allow_execute /sbin/runlevel if exec.realpath="/sbin/runlevel" exec.argv[0]="runlevel"
allow_execute /bin/cp if exec.realpath="/bin/cp" exec.argv[0]="cp"
allow_execute /usr/sbin/sshd if exec.realpath="/usr/sbin/sshd" exec.argv[0]="/usr/sbin/sshd"
allow_execute /bin/touch if exec.realpath="/bin/touch" exec.argv[0]="touch"
allow_read/write /dev/console
allow_execute /bin/unicode_start if exec.realpath="/bin/unicode_start" exec.argv[0]="/bin/unicode_start"
allow_read /var/run/sshd.pid
allow_write /dev/null
allow_capability SYS_KILL
allow_signal 15 <kernel> /usr/sbin/sshd
allow_execute /bin/usleep if exec.realpath="/bin/usleep" exec.argv[0]="usleep"
allow_execute /bin/rm if exec.realpath="/bin/rm" exec.argv[0]="rm"
allow_execute /usr/bin/killall if exec.realpath="/usr/bin/killall" exec.argv[0]="killall"
allow_execute /usr/bin/rhgb-client if exec.realpath="/usr/bin/rhgb-client" exec.argv[0]="/usr/bin/rhgb-client"
allow_execute /bin/sleep if exec.realpath="/bin/sleep" exec.argv[0]="sleep"
allow_signal 1 <kernel> /usr/sbin/sshd
allow_ioctl /dev/console 0x5401
allow_ioctl /etc/rc.d/init.d/sshd 0x5401
allow_ioctl /var/run/sshd.pid 0x5401
allow_ioctl /dev/pts/\$ 0x5401


#2010-01-10 12:27:20# profile=3 mode=enforcing (global-pid=4210) task={ pid=4210 ppid=4205 uid=0 gid=0 euid=0 egid=0 suid=0 sgid=0 fsuid=0 fsgid=0 state[0]=0 state[1]=0 state[2]=0 type!=execute_handler } path1={ uid=0 gid=0 ino=1766 major=0 minor=17 perm=0666 type=char dev_major=1 dev_minor=3 } path1.parent={ uid=0 gid=0 ino=962 perm=0755 }
<kernel> /etc/rc.d/init.d/sshd
allow_ioctl /dev/null 0x5401
Allow? ('Y'es/'N'o/'R'etry/'S'how policy/'A'dd to policy and retry):a
Enter new entry> allow_ioctl /dev/null 0x5401
Added 'allow_ioctl /dev/null 0x5401'.

The pathname /usr/lib/libpurple.so.0.6.3 was created. Appended to globally readable file.

The pathname /usr/lib/libpurple-client.so.0.6.3 was created. Appended to globally readable file.

----------------------------------------
#2010-01-10 12:29:35# profile=3 mode=enforcing (global-pid=4561) task={ pid=4561 ppid=4557 uid=0 gid=0 euid=0 egid=0 suid=0 sgid=0 fsuid=0 fsgid=0 state[0]=0 state[1]=0 state[2]=0 type!=execute_handler } path1={ uid=0 gid=0 ino=1507379 major=8 minor=1 perm=0755 type=file } path1.parent={ uid=0 gid=0 ino=1507329 perm=0755 } exec={ realpath="/bin/sleep" argc=2 envc=6 argv[]={ "sleep" "1" } envp[]={ "TERM=xterm" "PATH=/sbin:/usr/sbin:/bin:/usr/bin" "PWD=/" "LANG=en_US.UTF-8" "SHLVL=1" "_=/bin/sleep" } }
<kernel> /etc/rc.d/init.d/cups
allow_execute /bin/sleep
Allow? ('Y'es/'N'o/'R'etry/'S'how policy/'A'dd to policy and retry):a
Enter new entry> allow_execute /bin/sleep if exec.argc=2 exec.argv[1]="1"
Added 'allow_execute /bin/sleep if exec.argc=2 exec.argv[1]="1"'.

#2010-01-10 12:29:55# profile=3 mode=enforcing (global-pid=4561) task={ pid=4561 ppid=4557 uid=0 gid=0 euid=0 egid=0 suid=0 sgid=0 fsuid=0 fsgid=0 state[0]=0 state[1]=0 state[2]=0 type!=execute_handler } path1={ uid=0 gid=0 ino=1507379 major=8 minor=1 perm=0755 type=file } path1.parent={ uid=0 gid=0 ino=1507329 perm=0755 } exec={ realpath="/bin/sleep" argc=2 envc=6 argv[]={ "sleep" "1" } envp[]={ "TERM=xterm" "PATH=/sbin:/usr/sbin:/bin:/usr/bin" "PWD=/" "LANG=en_US.UTF-8" "SHLVL=1" "_=/bin/sleep" } }
<kernel> /etc/rc.d/init.d/cups
# wants to create domain
<kernel> /etc/rc.d/init.d/cups /bin/sleep
Allow? ('Y'es/'N'o/'R'etry):y

#2010-01-10 12:29:58# profile=3 mode=enforcing (global-pid=4561) task={ pid=4561 ppid=4557 uid=0 gid=0 euid=0 egid=0 suid=0 sgid=0 fsuid=0 fsgid=0 state[0]=0 state[1]=0 state[2]=0 type!=execute_handler } path1={ uid=0 gid=0 ino=707247 major=8 minor=1 perm=0644 type=file } path1.parent={ uid=0 gid=0 ino=688142 perm=0755 }
<kernel> /etc/rc.d/init.d/cups /bin/sleep
allow_read /usr/lib/locale/locale-archive
Allow? ('Y'es/'N'o/'R'etry/'S'how policy/'A'dd to policy and retry):a
Enter new entry> allow_read /usr/lib/locale/locale-archive
Added 'allow_read /usr/lib/locale/locale-archive'.

----------------------------------------
#2010-01-10 12:30:10# profile=3 mode=enforcing (global-pid=4630) task={ pid=4630 ppid=4629 uid=0 gid=0 euid=0 egid=0 suid=0 sgid=0 fsuid=0 fsgid=0 state[0]=0 state[1]=0 state[2]=0 type!=execute_handler } path1={ uid=0 gid=0 ino=955698 major=8 minor=1 perm=0666 type=socket } path1.parent={ uid=0 gid=0 ino=950312 perm=0755 }
<kernel> /usr/sbin/acpid
allow_unlink /var/run/acpid.socket
Allow? ('Y'es/'N'o/'R'etry/'S'how policy/'A'dd to policy and retry):a
Enter new entry> allow_unlink /var/run/acpid.socket if path1.type=socket
Added 'allow_unlink /var/run/acpid.socket if path1.type=socket'.

The pathname /usr/lib/libpurple.so.0.5.9 was deleted. Deleted from globally readable file.

The pathname /usr/lib/libpurple-client.so.0.5.9 was deleted. Deleted from globally readable file.

The "ccs-queryd" automatically appends shared libraries to exception policy using "allow_read" directive when the location of shared libraries in /etc/ld.so.cache has changed. The line

The pathname /usr/lib/libpurple.so.0.6.3 was created. Appended to globally readable file.

indicates that the pathname /usr/lib/libpurple.so.0.6.3 was appended to exception policy because it was created and was registered to /etc/ld.so.cache .

Also, the "ccs-queryd" automatically removes the pathname registered as globally readable files in exception policy when it was deleted. The line

The pathname /usr/lib/libpurple.so.0.5.9 was deleted. Deleted from globally readable file.

indicates that the pathname /usr/lib/libpurple.so.0.5.9 was removed from exception policy because it was deleted.

Policy violation might occur while updating packages due to unusual behavior such as restarting daemons. When a policy violation occurs, a prompt appears in the "ccs-queryd". The lines

#2010-01-10 12:29:35# profile=3 mode=enforcing (global-pid=4561) task={ pid=4561 ppid=4557 uid=0 gid=0 euid=0 egid=0 suid=0 sgid=0 fsuid=0 fsgid=0 state[0]=0 state[1]=0 state[2]=0 type!=execute_handler } path1={ uid=0 gid=0 ino=1507379 major=8 minor=1 perm=0755 type=file } path1.parent={ uid=0 gid=0 ino=1507329 perm=0755 } exec={ realpath="/bin/sleep" argc=2 envc=6 argv[]={ "sleep" "1" } envp[]={ "TERM=xterm" "PATH=/sbin:/usr/sbin:/bin:/usr/bin" "PWD=/" "LANG=en_US.UTF-8" "SHLVL=1" "_=/bin/sleep" } }
<kernel> /etc/rc.d/init.d/cups
allow_execute /bin/sleep
Allow? ('Y'es/'N'o/'R'etry/'S'how policy/'A'dd to policy and retry):

indicates that a process which belongs to the domain "<kernel> /etc/rc.d/init.d/cups" attempted to execute /bin/sleep in order to process the commandline "sleep 1" but the attempt was denied by policy, and the kernel is asking for your decision. Validate whether or not to permit the request and tell the kernel your decision. You can press "Y" to grant the request. You can press "N" to reject the request. You can press "R" to retry the request. You can press "S" to show domain policy for the process. You can press "A" to edit and append to domain policy and then retry the request.

Never grant access requests unconditionally. The cause of policy violation is not always updating packages, but may be malicious requests by attackers. If you grant access requests caused by malicious requests by attackers, the system gets intruded.

If "ccs-queryd" is running, the access requests that violated policy are kept pending. To avoid sleeping forever because of pending access requests, never logout (for example, detaching from screen(1)) while "ccs-queryd" is running.

Do a series of operations to confirm that programs that are protected by MAC can run properly. If some access permissions are missing, the messages will be printed to "ccs-queryd", so don't forget to monitor "ccs-queryd".

Note that "ccs-queryd" directly edits the policy currently loaded into the kernel. Thus, the changes made by "ccs-queryd" are lost by the system's shutdown. Be sure to run "ccs-savepolicy" to save the latest policy.

[root@tomoyo ~]# /usr/sbin/ccs-savepolicy

You have finished updating policies. Close the console or terminal you executed "ccs-queryd".


Return to index page.

sflogo.php