Info: Version 1.8.x is available.
Last modified: $Date: 2024-03-30 11:25:00 +0000 (Sat, 30 Mar 2024) $
This page describes how to use TOMOYO Linux's enforcing mode and how to handle policy violations which arises in 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.
Now the profile number of the /usr/sbin/httpd and descendant has changed to 3.
Press '@' key to switch to process list. Verify that /usr/sbin/httpd processes and descendant are assigned profile number 3.
And now, /usr/sbin/httpd processes and descendant are protected by MAC, for the profile 3 was configured for enforcing mode.
Press 'q' key to quit the policy editor.
Let's try an operation which is permitted by policy.
The operation was successfully completed, for sending mail is permitted by policy.
Let's try an operation which is not permitted by policy.
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.)
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.
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.
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.
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".