Info: Version 1.8.x is available.

Japanese Page

Last modified: $Date: 2024-03-31 15:45:12 +0000 (Sun, 31 Mar 2024) $

The world of TOMOYO Linux
The seventh installment: "Let's try various functionalities."

Contents of this installment.

By now in this series, I explained access control on files. Access control on files prevents accessing unnecessary programs and data files and plays basic role for improving security using secure OS. But access control on files alone is not sufficient. In this installment, I explain major access controls which TOMOYO Linux provides, mainly access control on networks.

About access control on networks

By default, Linux provides iptables for doing packet filtering. TOMOYO Linux provides similar functionality, but TOMOYO Linux's access control on networks can perform packet filtering for per TOMOYO Linux's domain and per user ID basis, and easy to configure. You can use TOMOYO Linux's access control on networks even if iptables is too difficult for you to configure. (But note that there are functionalities which iptables can provide but TOMOYO Linux can't provide, for TOMOYO Linux is independent with iptables.)

Coverage of access control on networks

Coverage of TOMOYO Linux's access control on networks is shown in Fig. 1.

♦ Fig. 1  Coverage of access control on networks
TCP protocol / UDP protocol / IP protocol
IPv4 network address / IPv6 network address
Port number (for TCP and UDP) / Protocol number (for IP)

By using TOMOYO Linux's access control on networks, you can allow, for example, svn command which is executed by a user whose user ID is 500 and who logged in via /usr/sbin/sshd can communicate with port 80 on host 202.221.179.11 using TCP protocol. I explain steps to configure in following sections.

Preparation

You can specify access control on networks for per a domain basis like access control on files. For this installment, I create 3 profiles for "a profile for learning mode for network only" "a profile for permissive mode for network only" "a profile for enforcing mode for network only".

(1) Creating profiles

As a preparation for access control on network, create profile 5 to 7. Append lines listed in Fig. 2 to the bottom of /etc/ccs/profile.conf .

♦ Fig. 2  Lines to be appended to /etc/ccs/profile.conf
5-COMMENT=Learning Mode (Network Only)
5-CONFIG::network={ mode=learning }
6-COMMENT=Permissive Mode (Network Only)
6-CONFIG::network={ mode=permissive }
7-COMMENT=Enforcing Mode (Network Only)
7-CONFIG::network={ mode=enforcing }

Save the file and then reflect the changes by doing command in Fig. 3.

♦ Fig. 3  Reflect the changes
# /usr/sbin/ccs-loadpolicy p

(2) Determining target domains

Target domains for applying access control on network are arbitrary. In this installment, I choose domains under currently operating shell sessions as target domains. You can see the domain which current process belongs to by doing "/bin/cat < /proc/ccs/self_domain". If the domain which currently operating shell sessions belong is specified using "keep_domain" keyword, delete the "keep_domain" keyword for this section using policy editor. (This is just for making it easier for you to understand. You don't need to delete "keep_domain" keyword when you apply on actual environment.) Note that the IP addresses and port numbers learned may differ depending on your environment.

Let TOMOYO Linux learn the permissions

(1) Examples for client applications

Change a domain which current process belongs to and its descendent domains to learning mode by doing commands listed in Fig. 4. (You may specify actual domainname as string parameter instead of redirection.)

♦ Fig. 4  Change a domain which current process belongs to and its descendent domains to learning mode
# xargs -0 /usr/sbin/ccs-setprofile -r 5 < /proc/ccs/self_domain

As an example command that uses networks, let's access http://www.osdn.jp/ using /usr/bin/curl command. (Fig. 5)

♦ Fig. 5  Execute /usr/bin/curl command
# curl http://www.osdn.jp/ > /dev/null

If /usr/bin/curl command is not available, you can use other commands like /usr/bin/wget command or /usr/kerberos/bin/telnet command. Run the policy editor and browse permissions for the domain for /usr/bin/curl command. (Fig. 6)

♦ Fig. 6  Policy configuration for a domain for /usr/bin/curl command
fig-7-6.png

Lines starting with "allow_network" keyword are permissions for access control on networks. "allow_network UDP connect 192.168.1.2 53" allows communicating with port 53 (i.e. DNS service) on host 192.168.1.2 using UDP protocol. Also, "allow_network TCP connect 202.221.179.11 80" allows communicating with port 80 (i.e. HTTP service) on host 202.221.179.11 (this is IP address for www.osdn.jp as of this writing) using TCP protocol.

(2) Examples for server applications

In this section, let's login to SSH service using /usr/bin/ssh command. (If you don't have SSH service, you can use other services like HTTP.) If "initialize_domain /usr/sbin/sshd" is specified in the exception policy (it should be specified by init_policy command which I executed in the first installment of this series), /usr/sbin/sshd runs in the "<kernel> /usr/sbin/sshd" domain. Thus, assign a profile for learning mode to the "<kernel> /usr/sbin/sshd" domain. (Fig. 7)

♦ Fig. 7  Assign a profile for learning mode to "<kernel> /usr/sbin/sshd" domain
# /usr/sbin/ccs-setprofile 5 '<kernel> /usr/sbin/sshd'

Then, login to localhost using ssh command (Fig. 8) and run the policy editor and browse permissions for "<kernel> /usr/sbin/sshd" domain. (Fig. 9)

♦ Fig. 8  Login to localhost using ssh command
# ssh localhost
♦ Fig. 9  Policy configuration for "<kernel> /usr/sbin/sshd" domain
fig-7-9.png

"allow_network TCP accept 0:0:0:0:0:ffff:7f00:1 34561" allows accepting TCP connections from port 34561 on host (IPv6 address) 0:0:0:0:0:ffff:7f00:1.

You can apply conditions to permissions for access control on networks as well as permissions for access control on files. For example, you can restrict remote server's IP addresses based on user ID by using process's user ID as conditions. (Fig. 10)

♦ Fig. 10  Restricting remote servers based on user ID
allow_network TCP connect 202.221.179.11 80 if task.uid=500
allow_network TCP connect 66.35.250.203 80 if task.uid=501

Regarding IP sockets, you specify protocol number instead of port number. I explain using ping command as an example. Execute command in Fig. 11 and then execute the policy editor and browse permissions for the domain for ping command. (Fig. 12)

♦ Fig. 11  Executing ping command
# ping -c 4 www.osdn.jp
♦ Fig. 12  Policy configuration for the domain for ping command
fig-7-12.png

You can see a line "allow_network RAW connect 202.221.179.11 1". Fig. 12 shows that the domain which ping command is running is allowed to communicate with host 202.21.179.21 using IP sockets with protocol number 1 (i.e. ICOMP).

Let's tune policy

After you let TOMOYO Linux learn permissions, verify the permissions using permissive mode. Assign profile 6 to change to permissive mode. (Fig. 13)

♦ Fig. 13  Change to permissive mode by assigning profile 6
# xargs -0 /usr/sbin/ccs-setprofile -r 6 < /proc/ccs/self_domain

(1) Patternizing IP addresses

You need to patternize IP address ranges for doing access control on networks as well as you patternized file's pathnames for doing access control on files. To patternize IP addresses, specify address ranges using "StartAddress-EndAddress" format like Fig. 14. No space is permitted around "-".

♦ Fig. 14  Specifying IPv4 address ranges
xxx.xxx.xxx.xxx-yyy.yyy.yyy.yyy

You can specify IPv6 address as well as IPv4 address. But "::" and "." are not supported for IPv6 address. You need to specify IPv6 address using format like Fig. 15. Also, be sure to specify all possible IP addresses if target servers has multiple IP addresses (e.g. load balancing).

♦ Fig. 15  Specifying IPv6 address
xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx

(2) Patternizing port numbers

Generally, the port number which servers use for accepting connections from clients are fixed, but the port number which clients use for establishing connections with servers are not fixed. Therefore, you need to specify possible port number ranges which clients might use when giving permissions to server side programs. To patternize, specify port number ranges using "StartPort-Endport" format like Fig. 16. No space is permitted around "-". Three patterns listed in Fig. 17 are port number ranges frequently used.

♦ Fig. 16  Specifying port number ranges
xxxxx-yyyyy
♦ Fig. 17  Frequently used port number ranges
1024-65535
32768-61000
600-1023

The first pattern is for port numbers which normal client programs choose when establishing connections with server programs, and you likely specify this range for server programs. The second pattern is for port numbers which are specified in /proc/sys/net/ipv4/ip_local_port_range . Normal client programs choose an unused port from this range when establishing connections with server programs, and you likely specify this range for client programs. Check /proc/sys/net/ipv4/ip_local_port_range when determining the second pattern.

The last pattern is for port numbers used by programs like portmap command which require privileged port numbers (port numbers smaller than 1024) for communication. The actual port numbers required by such programs may be different. The easy way for determining whether patternizing port numbers are necessary or not is to execute programs for several times. For example, permissions with contiguous port numbers like Fig. 18 will be appended by learning mode. Thus, guess required port number ranges from the result of learning mode.

♦ Fig. 18  Example of permissions with contiguous port numbers
allow_network TCP bind 127.0.0.1 610
allow_network TCP bind 127.0.0.1 611
allow_network TCP bind 127.0.0.1 612
allow_network TCP bind 127.0.0.1 613

If you find permissions in Fig. 18, you likely need permissions in Fig. 19.

♦ Fig. 19  Patternized permissions based on Fig. 18
allow_network TCP bind 127.0.0.1 600-1023

If you find permissions in Fig. 20, you likely need permissions in Fig. 21 or Fig. 22.

♦ Fig. 20  Example of permissions with contiguous port numbers
allow_network TCP accept 127.0.0.1 32780
allow_network TCP accept 127.0.0.1 32781
allow_network TCP accept 127.0.0.1 32782
allow_network TCP accept 127.0.0.1 32783
allow_network TCP accept 127.0.0.1 32784
♦ Fig. 21  Patternized permissions based on Fig. 20
allow_network TCP accept 127.0.0.1 1024-65535
♦ Fig. 22  Patternized permissions based on Fig. 20
allow_network TCP accept 127.0.0.1 32768-61000

Let's enforce access control on networks

When you became sure that you gave enough permission, let's enforce access control on networks. Assign profile 7 to change to enforcing mode. (Fig. 23)

♦ Fig. 23  Change to enforcing mode by assigning profile 7
# xargs -0 /usr/sbin/ccs-setprofile -r 7 < /proc/ccs/self_domain

Note that profile 5 to 7 does not perform access control on files. By using ccs-queryd which I explained in the fourth installment of this series, you can interactively append missing permissions. I think you understood that you can break access control on networks provided by iptables by using TOMOYO Linux.

About access control on capabilities

Linux kernel 2.2 and later supports POSIX capabilities. Capabilities realize secure OS's basic concept "least privileges" and are used for restricting use of various privileged operations for per a process basis. You can find list of capabilities which Linux supports in /usr/include/linux/capability.h . However, since CAP_SYS_ADMIN privilege is used for various purposes, we cannot expect fine grained restriction. Therefore, TOMOYO Linux defined and uses original capabilities. (Hereafter, capabilities refers to TOMOYO Linux's capabilities rather than POSIX's capabilities.)

While TOMOYO Linux uses original capabilities that are not compatible with POSIX capabilities, TOMOYO Linux's capabilities are not visible from userland applications. Thus, you don't need to modify userland programs. TOMOYO Linux 1.7.4 uses capabilities listed in Fig. 24.

♦ Fig. 24  Capabilities defined in TOMOYO Linux 1.7.4
TypeMeaning
inet_tcp_createPermit creation of TCP sockets.
inet_tcp_listenPermit TCP socket's listen operation.
inet_tcp_connectPermit TCP socket's connect operation.
use_inet_udpPermit use of UDP sockets.
use_inet_ipPermit use of RAW sockets.
use_routePermit use of ROUTE sockets.
use_packetPermit use of PACKET sockets.
use_kernel_modulePermit use of create_module(2) init_module(2) delete_module(2) syscall.
create_fifoPermit creation of FIFO using mknod(2) syscall.
create_block_devPermit creation of block device using mknod(2) syscall.
create_char_devPermit creation of character device using mknod(2) syscall.
create_unix_socketPermit creation of UNIX domain sockets using mknod(2) syscall.
SYS_MOUNTPermit use of mount(2) syscall.
SYS_UMOUNTPermit use of umount(2) syscall.
SYS_REBOOTPermit use of reboot(2) syscall.
SYS_CHROOTPermit use of chroot(2) syscall.
SYS_KILLPermit use of kill(2) tkill(2) tgkill(2) syscall with non 0 signal.
SYS_VHANGUPPermit use of vhangup(2) syscall.
SYS_TIMEPermit use of stime(2) settimeofday(2) adjtimex(2) syscall.
SYS_NICEPermit use of nice(2) setpriority(2) syscall.
SYS_SETHOSTNAMEPermit use of sethostname(2) setdomainname(2) syscall.
SYS_LINKPermit use of link(2) syscall.
SYS_SYMLINKPermit use of symlink(2) syscall.
SYS_RENAMEPermit use of rename(2) syscall.
SYS_UNLINKPermit use of unlink(2) syscall.
SYS_CHMODPermit use of chmod(2) fchmod(2) syscall.
SYS_CHOWNPermit use of chown(2) fchown(2) lchown(2) syscall.
SYS_IOCTLPermit use of ioctl(2) compat_sys_ioctl(2) syscall.
SYS_KEXEC_LOADPermit use of kexec_load(2) syscall.
SYS_PIVOT_ROOTPermit use of pivot_root(2) syscall.
SYS_PTRACEPermit use of ptrace(2) syscall.
conceal_mountPermit use of mount(2) syscall that will hide existing mounts.

In this section, I explain about privilege for doing mount operation (i.e. SYS_MOUNT ) as an example. Since TOMOYO Linux performs access control using pathnames, it is an absolutely important assumption that filesystems are mounted as the administrator intended. It is annoying thing if any processes running as "root" user can freely mount filesystems. Thus, by using capabilities, you can restrict domains which can do mount operations. Steps for doing access control on capabilities are the same with doing access control on networks. Firstly, specify capabilities you want to control in the profiles. Append lines listed in Fig. 25 to the bottom of /etc/ccs/profile.conf .

♦ Fig. 25  Lines to be appended to /etc/ccs/profile.conf
9-CONFIG::capability::SYS_MOUNT={ mode=learning }
10-CONFIG::capability::SYS_MOUNT={ mode=enforcing }

Unlike files and networks, capabilities do not have operands. All necessary capabilities are given by simply using learning mode. Thus, a profile for permissive mode is omitted in Fig. 25. Save the file and then reflect the changes by doing command in Fig. 3.

For explanation, I firstly use a profile for enforcing mode. (Fig. 26)

♦ Fig. 26  Assign a profile for enforcing mode
# xargs -0 /usr/sbin/ccs-setprofile -r 10 < /proc/ccs/self_domain

Then, mount tmpfs somewhere. (Fig. 27)

♦ Fig. 27  Mounting tmpfs
# mount -t tmpfs none /tmp/
mount: permission denied

The mount operation was rejected. This is because the domain which mount command belongs to was not given a capability for doing mount operation. Next, assign a profile for learning mode. (Fig. 28)

♦ Fig. 28  Assign a profile for learning mode
# xargs -0 /usr/sbin/ccs-setprofile -r 9 < /proc/ccs/self_domain

Again, mount tmpfs somewhere. (Fig. 29)

♦ Fig. 29  Mounting tmpfs
# mount -t tmpfs none /tmp/

This time, the mount operation succeeded. Run the policy editor and find the domain for mount command and browse permissions for that domain. (Fig. 30)

♦ Fig. 30  Permission "allow_capability SYS_MOUNT" was learned
fig-7-30.png

You can find that a permission "allow_capability SYS_MOUNT" was learned. Now, you can forbid mount operations from domains without SYS_MOUNT capability by assigning a profile for enforcing mode.

You might notice that it is not sufficient to restrict whether mount operation is permitted or not , for the process can do arbitrary mount operations if mount operation is permitted. In fact, that is true. TOMOYO Linux's access control on files includes ability to restrict the combination of mount device and mount point and filesystem type and mount flags. Thus, if you do operations listed in Fig. 29 with a profile for learning mode for access control on files, "allow_mount none /tmp/ tmpfs 0" will appear in Fig. 30.

About access control on signals

TOMOYO Linux can do access control on signal numbers and signal targets. Steps for doing access control on signals are the same with doing access control on networks. Append lines listed in Fig. 31 to the bottom of /etc/ccs/profile.conf .

♦ Fig. 31  Lines to be appended to /etc/ccs/profile.conf
11-CONFIG::ipc::signal={ mode=learning }
12-CONFIG::ipc::signal={ mode=enforcing }

Save the file and then reflect the changes by doing command in Fig. 3.

I assume below operations are done from "<kernel> /usr/sbin/sshd /bin/bash" domain (i.e. login shell executed by /usr/sbin/sshd ). Make sure that "keep_domain <kernel> /usr/sbin/sshd /bin/bash" is not specified in the exception policy. Firstly, execute /bin/sleep command. (Fig. 32)

♦ Fig. 32  Execute /bin/sleep
# sleep 100

At this state, open another window and login to the system. For explanation, I firstly use a profile for enforcing mode. (Fig. 33)

♦ Fig. 33  Assign a profile for enforcing mode
# xargs -0 /usr/sbin/ccs-setprofile -r 12 < /proc/ccs/self_domain

Then, get the process ID of running /bin/sleep command and send a signal to that process ID. (Fig. 34. Use external /bin/kill command rather than shell's built-in kill command.)

♦ Fig. 34  Send signal to process ID of /bin/sleep command
# pidof sleep
4649
# /bin/kill -15 4649
kill 4649: Operation not permitted

The kill operation was rejected. This is because the domain which /bin/kill command belongs to was not given permission for sending signals. Next, assign a profile for learning mode (Fig. 35) and resend the signal. (Fig. 36)

♦ Fig. 35  Assign a profile for learning mode
# xargs -0 /usr/sbin/ccs-setprofile -r 11 < /proc/ccs/self_domain
♦ Fig. 36  Send signal to process ID of /bin/sleep command again
# /bin/kill -15 4649

This time, signal operation succeeded. Run the policy editor and find the domain for kill command and browse permissions for that domain. (Fig. 37)

♦ Fig. 37  Permissions given to the domain for kill command
fig-7-37.png

You can find a permission "allow_signal 15 <kernel> /usr/sbin/sshd /bin/bash /bin/sleep" was learned. This permission allows sending signal 15 (i.e. SIGTERM) to "<kernel> /usr/sbin/sshd /bin/bash /bin/sleep" domain and its descendent domains. Since TOMOYO Linux's domains forms hierarchal structure starting with "<kernel>", "allow_signal 15 <kernel>" will allow sending signal 15 to any processes. Also, as exceptions, sending signals to the same domain (e.g. threads in current process) is always permitted, and sending signal 0 is always permitted.

Trailer

In this installment, I explained mainly access control on networks. I think you understood that you can restrict domains that can use networks and apply powerful and flexible access controls using TOMOYO Linux. In the next installment, I explain steps for restricting login sessions. Don't miss it!

Go back to the sixth installment.  Proceed to the eighth installment.


Return to index page.

sflogo.php