Notes for TOMOYO Linux project This is a handy Mandatory Access Control patch for Linux kernels. This patch is released under the GPL. Project URL: http://tomoyo.sourceforge.jp/ The authors of this patch (hereafter, we) don't have much experience in kernel programming. We are worried that this patch would contain some mistakes such as missing hooks, improper location of hooks, potential deadlocks. There would be better way of implementation. All kinds of comments, pointing the errors and suggestions are welcome. We do hope this patch reduces the labor of server security management and you enjoy the life with Linux. This project was very inspired by the comic "Card Captor SAKURA", one of the CLAMP's masterworks. The names SAKURA and TOMOYO and SYAORAN were borrowed from the comic with the heartfelt thanks to CLAMP. ChangeLog: Version 1.0 2005/11/11 First release. Fix 2005/11/18 @ Add setattr() missing hook in SYAORAN fs. setattr() checking for special inode was missing. Fix 2005/11/25 @ Allow initrd.img include /sbin/init . Since version 1.0 loads policy when /sbin/init is called for the first time, initrd.img without the policy directory mustn't start /sbin/init . This forced users not to use initrd.img that includes /sbin/init . I modified to delay loading policy if the policy directory doesn't exist and wait for /sbin/init being called again. Fix 2005/12/02 @ Use lookup_one_len() instead of lookup_hash(). Kernel 2.6.15 changed parameters for lookup_hash(). I modified to use lookup_one_len() to keep compatibility. Fix 2005/12/06 @ Add S_ISDIR() check in SYAORAN fs. Malicious configuration file that attempts to create an inode under non-directory inode caused segmentation fault. Version 1.0.1 2005/12/08 Minor update release. Fix 2006/01/04 @ Add CheckWritePermission() check in unix_bind(). I modified to check write permission in unix_bind(), for sys_mknod(S_IFSOCK) checks write permission. @ Show hook version in proc_misc_init(). The hook part of this patch depends on the kernel's version, while the rest part of this patch doesn't. I added the hook version so that the administrator can know the last modified date of the hooks. @ Move permission checks from filp_open() to open_namei(). I moved the location of checking MAC's permission from filp_open() to open_namei(). @ Fix an error in filp_open(). (only 2.6.15-rc5) This error was only in the patch 2.6.15-rc5 and was fixed in the patch for 2.6.15. Fix 2006/01/12 @ Add /proc/ccs/info/self_domain. I added /proc/ccs/info/self_domain so that the userland programs can know the name of domain they belong to if necessary. Fix 2006/01/13 @ Merge constants for CheckTaskCapability(). I merged *_INHERITABLE_* and *_LOCAL_* to avoid always calling CheckTaskCapability() with both constants. @ DropTaskCapability() returns -EAGAIN on success. DropTaskCapability() must not return 0 on success, for DropTaskCapability() is called from do_execve(). @ Fix an error for chroot() permission check. The chroot() restriction was not working due to the following mistake. CheckChRootPermission() || CheckTaskCapability() returns 0 or 1, while CheckChRootPermission() | CheckTaskCapability() returns 0 or -EPERM. Fix 2006/01/17 @ Suppress some of debug messages in TOMOYO. I added KERN_DEBUG to suppress some of debug messages. Fix 2006/01/19 @ Remove isRoot() checks in AddChrootACL() and AddMountACL(). I found a program that needs to chroot by non-root. So, I stopped checking uid=euid=0 for these functions so that "accept mode" can append ACLs. The isRoot() is checked at AddChrootPolicy() and AddMountPolicy(). @ Map NULL device name to "" in AddMountACL(). VMware mounts vmware-hgfs with NULL device name. So I mapped NULL device name to "". Fix 2006/01/20 @ Suppress some of debug messages in SAKURA. I added KERN_DEBUG to suppress some of debug messages. @ Call panic() if failed to load given profile. Call panic() if profile index was given via CCS= parameter but the profile doesn't exist. If CCS= parameter is not given, the kernel attempts to load profile 0, but it doesn't call panic() if profile 0 doesn't exist. Fix 2006/01/24 @ Use full_name_hash() for IsGloballyReadableFile(). I modified to use full_name_hash() for faster scan. @ Add signal checking condition in CheckSignalACL(). The documentation says "if the target domain's domainname starts with the source domain's domainname, it is always granted" but actually it isn't. I'll change the documentation instead of changing the source code. Also, checking for pid = -1 was missing. This error was fixed. Fix 2006/02/09 @ Use mutex_lock()/mutex_unlock instead of down()/up(). Kernel 2.6.16 changed members of "struct inode". I modified to use mutex_lock()/mutex_unlock() for after 2.6.16 and down()/up() for before 2.6.16. Version 1.0.2 2006/02/14 Many bug-fixes release. Fix 2006/02/21 @ Divide generic-write permission into individual write permissions. Write permission was divided into the following permissions. 'mkdir' for creating directory. 'rmdir' for deleting directory. 'create' for creating regular file. 'unlink' for deleting non-directory. 'mksock' for creating UNIX domain socket. 'mkfifo' for creating FIFO. 'mkchar' for creating character device. 'mkblock' for creating block device. 'link' for creating hard link. 'symlink' for creating symbolic link. 'rename' for renaming directory or non-directory. 'truncate' for truncating regular file. The permission check for opening files is done using conventional read/write/execute permission. @ Add /proc/ccs/info/mapping. I added /proc/ccs/info/mapping so that the userland programs can know the mapping of individual write permissions. Fix 2006/02/27 @ Fix handling of trailing '\*' in PathMatchesToPattern(). PathMatchesToPattern("/tmp/", "/tmp/\*") returned true because "\*" matches to "more than or equals to 0 character until '/' or end". But since this is a comparison between directory and non-directory, this should not match. This behavior causes the following security risks. In enforce mode, allowing "2 /tmp/\*" grants "mkdir /tmp/" and "rmdir /tmp/" which should be granted only when "2 /tmp/" is allowed. In accept mode, "mkdir /tmp/" or "rmdir /tmp/" appends "2 /tmp/\*" into the domain policy if "file_pattern /tmp/\*" is in the exception policy. I changed not to ignore trailing '\*' in the pattern if pathname ends with '/'. Fix 2006/03/01 @ Add missing spinlock in GetAbsolutePath(). vfsmount_lock was missing. Fix 2006/03/08 @ Add support for "shared subtree" mount operations. Kernel 2.6.15 introduced "shared subtree" functionality. But CheckMountPermission() couldn't recognize flags for do_change_type(). @ Add support for more mount flags. atime/noatime, diratime/nodiratime, recurse/norecurse flags are supported. Fix 2006/03/20 @ Check port numbers for only AF_INET/AF_INET6. CheckBindEntry() and CheckConnectEntry() should check port numbers only when the given address family is either AF_INET or AF_INET6, for address family such as AF_UNSPEC could be passed to bind() and connect() for PF_INET/PF_INET6 sockets. Fix 2006/03/27 @ Use /proc/self/ rather than /proc/\$/ for current process. GetAbsolutePath() now uses "self" instead of pid if current process refers to information related to itself. This exception violates the rule "TOMOYO Linux's pathnames don't contain symbolic links before the last '/'", but I think it worth to do so. The following are the merits gained by this exception. Prevent administrators from granting redundant permissions when a process needs to refer to only current process's information. Allow administrators make current process's information always readable using 'allow_read' directive. Version 1.1 2006/04/01 Functionality enhancement release. Fix 2006/04/03 @ Use queue instead of fixed sized array for audit log. WriteAuditLog() now uses queue to save statically allocated memory. Administrators can give any size for audit logs at runtime. @ Use kzalloc() instead of kmalloc() + memset(). kmalloc() + memset() were replaced with kzalloc(). Fix 2006/04/04 @ Support "delayed enforcing" mode. Until now, access request was immediately rejected if policy doesn't allow that access and the system is running in enforce mode. Sometimes, especially after updating softwares, some unexpected access requests arise from proper procedure. Such access requests should be granted because they are not caused by malicious attacks. So I introduced a mechanism to allow administrator some grace to decide to grant or reject such access requests. This mechanism is implemented in the following manner. "Don't return immediately if permission denied." "Sleep for a while waiting administrator's decision." "Return successfully if administrator tells to do so." Fix 2006/04/12 @ Fix handling of prefix in GetAbsolutePath(). Some objects doesn't have prefix "/". Pipe has prefix "pipe:" and socket has prefix "socket:". GetAbsolutePath() couldn't handle prefixes other than '/' properly. @ Remove IsCorrectPath() checks for File Access Control functions. File Access Control functions accepted only pathnames that start with '/' because these functions assumed pathnames returned by GetAbsolutePath() always start with '/'. However, I found a program that opens an unnamed pipe via (probably) /proc/PID/fd/ directory. (You can see entries like "pipe:[number]" if you run "ls -l /proc/*/fd/".) Now, File Access Control functions have to accept pathnames that don't start with '/'. So, I stopped checking IsCorrectPath(). Fix 2006/04/19 @ Fix handling of NULL nameidata in vfs_open(). In 2.6 kernels, NFS daemon and sys_mq_open() call vfs_create() with NULL nameidata. In such cases, CheckSingleWritePermission() must not be called. Version 1.1.1 2006/05/15 Functionality enhancement release. Fix 2006/05/16 @ Support program files aggregation. Until now, programs that have no fixed names and their parent programs had to be run in a trusted domain since it is impossible to use patterns for granting execute permission and defining domains. I introduced a mechanism to aggregate similar programs using 'aggregator' directive. Some examples: 'aggregator /tmp/logrotate.\?\?\?\?\?\? /tmp/logrotate.tmp' to run all temporary programs for logrotate as /tmp/logrotate.tmp 'aggregator /usr/bin/tac /bin/cat' to run /usr/bin/tac and /bin/cat as /bin/cat Fix 2006/05/18 @ Unlimit max count for audit log. I forgot to replace MAX_GRANT_LOG and MAX_REJECT_LOG with INT_MAX so that administrators can give any size for audit logs at runtime. Fix 2006/05/22 @ Support individual domain ACL removal. Until now, to remove ACLs from a domain, administrator had to once delete and recreate that domain, which wastes a lot of memory. I introduced a mechanism to remove domain ACL without deleting and recreating domains. Administrator can delete domains or remove ACLs from domains via /proc/ccs/policy/domain_policy . /proc/ccs/policy/delete_domain and /proc/ccs/policy/update_domain were removed. Fix 2006/05/30 @ Add missing spinlock in SAKURA_MayMount(). vfsmount_lock was missing. Version 1.1.2 2006/06/02 Functionality enhancement release. Fix 2006/06/13 @ Merge tomoyo_connect.c and tomoyo_bind.c into tomoyo_port.c I merged these files that have only difference CONNECT and BIND, that are likely to be enabled both or neither. @ Add CONFIG_TOMOYO_AUDIT option. I made auditing functions as optional because some Linux boxes may have not enough disk space to store audit logs. Fix 2006/06/15 @ Support use of symbolic links for program execution. Until now, domains for programs executed by dereferencing symbolic links were defined using dereferenced pathnames. This was inconvenient for some Linux boxes who use busybox but can't keep hard links of busybox. I introduced a mechanism to allow using pathnames of symbolic links using 'alias' directive. Some examples: 'alias /sbin/busybox /bin/ls' to run /bin/ls (which is a symbolic link to /sbin/busybox) as /bin/ls if /bin/ls is executed. 'alias /bin/bash /bin/sh' to run /bin/sh (which is a symbolic link to /bin/bash) as /bin/sh if /bin/sh is executed. Fix 2006/06/21 @ Use ccs_alloc() instead of kzalloc(). To detect memory leaks, I added a wrapper for tracing kmalloc() and kfree(). There is no way to detect memory leaks caused by ccs-*.txt . Version 1.1.3 2006/07/13 Functionality enhancement release. Fix 2006/07/14 @ Change behavior of pathname pattern matching. Until now, it was impossible to use patterns like "\*.txt" because "\*" matched to more than 0 characters until next '/'. Now, "\*" matches to more than 0 characters. Until now, it was impossible to use patterns like "\$00" because "\$" matched to more than 1 digits until next non digit character. Now, "\$" matches to more than 1 digits. Also, new patterns "\x" "\X" "\a" "\A" "\@" are added. Fix 2006/07/21 @ Add CONFIG_TOMOYO_NETWORK option. Until now, only port numbers for TCP and UDP were controllable. Now, the combination of IPv4/IPv6 address and port numbers for TCP and UDP is controllable. CONFIG_TOMOYO_NETWORKPORT became obsolete. Fix 2006/07/25 @ Change matching rule for CheckFileACL(). Until now, only first entry that matched to the requested pathname was used for permission checking. For example, two entries "2 /tmp/file-\$.txt" "4 /tmp/fil\?-0.txt" are given in this order and requested pathname is "/tmp/file-0.txt", the "2 /tmp/file-\$.txt" is used. But if two entries "4 /tmp/fil\?-0.txt" "2 /tmp/file-\$.txt" are given in this order, the "4 /tmp/fil\?-0.txt" is used. This may potentially cause trouble because the result of permission checks depends on the order of entries. Now, all entries that matched to the requested pathname are used for permission checking so that the result of permission checks doesn't depend on the order of entries. Fix 2006/07/27 @ Support RAW IPv4/IPv6 control. Some programs such as 'ping' and 'traceroute' use raw IP socket. Now, the combination of IPv4/IPv6 address and protocol numbers for IP is controllable. Fix 2006/08/04 @ Add filename and argv[0] comparison check. The domain transition was done based on filename passed to do_execve(), while the behavior was defined based on argv[0]. There is no problem if the filename is argv[0]-unaware application. But if argv[0]-aware, access control bypassing happens if the process transits to trusted domain but behaves as different program. For example, when the administrator specifies domain for /bin/ls as trusted but both /bin/ls and /bin/cat are links to /sbin/busybox , a cracker can run /bin/cat in a trusted domain if the cracker succeeds to invoke do_execve() with filename = "/bin/ls" and argv[0] = "/bin/cat". I introduced a keyword that permits the mismatch of basename of filename and argv[0]. Fix 2006/08/10 @ Support ID based condition checks. It was impossible to use process id (uid and gid and so on) for checking individual domain ACL. Now it became possible to use process id for checking individual domain ACL. For example, "1 /bin/sh if task.euid!=0" allows the domain to execute /bin/sh only when the process's euid is not 0, and "6 /home/\*/\* if task.uid=path1.uid" allows the domain to read-write user's home directory only when the file's owner matches to the process's uid. Fix 2006/08/22 @ Fix ROUNDUP() in fs/realpath.c . Alignment using sizeof(int) may be inappropriate for 64bit environment. I changed to use the larger size of 'void *' and 'long' instead of 'int'. For environment where sizeof(int) = sizeof(long) = sizeof(void *), this change has no effect. Version 1.2 2006/09/03 Functionality enhancement release. Fix 2006/09/30 @ Fix CheckFilePerm() in fs/tomoyo_file.c . The location to call path_release() was too early. Fix 2006/10/02 @ Support per-domain profile. It became possible to assign different profiles for different domains. This will help administrators using building up approach. Fix 2006/10/05 @ Change parameters for CheckFilePerm(). I was re-resolving pathnames inside CheckFilePerm() even though the caller function already resolved them. So I changed to pass dentry and vfsmount instead of pathname, and removed changes made on 2006/09/30. Fix 2006/10/06 @ Support deny_rewrite and allow_rewrite permission. It became possible to make regular files append-only using "deny_rewrite" directive in exception policy and override it using "allow_rewrite" directive in domain policy. Regular files specified using "deny_rewrite" directive can't be open()ed with O_TRUNC or without O_APPEND, can't be truncate()ed or ftruncate()ed, can't be turned O_APPEND flag off using fcntl(F_SETFL) unless specified using "allow_rewrite" directive. Fix 2006/10/12 @ Enable configuration options by default for kernel config. CONFIG_SAKURA and CONFIG_TOMOYO are now 'y' by default and CONFIG_SYAORAN is now 'm' by default. Fix 2006/10/13 @ Use external policy loader. Until now, policies are loaded when /sbin/init starts and initial control levels are switched using CCS= parameter. But since some boxes have to fixate kernel command line options at compilation time, I think it will become more flexible by running external policy loader using init= parameter so that initial control levels can be specified before /sbin/init starts. Call panic() if initial control levels are not specified. Fix 2006/10/16 @ Add missing parameter in FindNextDomain(). 'struct file' was needed for allowing 'if path1.*' checks. Fix 2006/10/23 @ Print error messages in CheckFlags(). Some users seem to have troubles picking up all necessary entries for the configuration file of SYAORAN filesystem since makesyaoranconf can't pick up entries that are nonexistent at the time. I added error message so that users can find missing entries using dmesg. Fix 2006/10/24 @ Change /proc/ccs/info/self_domain . I changed /proc/ccs/info/self_domain to return the domain of open time rather than first read time. This modification makes shell's redirection usage more convenient since redirection opens file but doesn't read at the time. 'cat < /proc/ccs/info/self_domain' will return the domain of shell, and 'cat /proc/ccs/info/self_domain' will return the domain of cat . Fix 2006/11/06 @ Replace MAX_ENFORCE_GRACE with ALLOW_ENFORCE_GRACE. Since it was inconvenient that requests that are waiting for supervisor's decision are rejected automatically when MAX_ENFORCE_GRACE seconds has elapsed, I modified WriteAnswer() reset timeout counter whenever a supervisor's decision is written and I modified ccs-queryd write a dummy decision every seconds so that the requests won't be rejected automatically as long as ccs-queryd is running. This change made MAX_ENFORCE_GRACE's meaning boolean. So I fixated MAX_ENFORCE_GRACE to 10 seconds and removed MAX_ENFORCE_GRACE parameter. To allow administrators selectively enable "delayed enforcing" mode, I added ALLOW_ENFORCE_GRACE parameter. The behavior of "delayed enforcing" mode is defined in the following order. (1) The requests are rejected immediately if ALLOW_ENFORCE_GRACE=0. (2) The requests are rejected immediately if nobody is opening /proc/ccs/policy/query interface. (3) The requests won't be rejected automatically if ALLOW_ENFORCE_GRACE=1 and ccs-queryd is running. (4) The requests will be rejected in 10 seconds if somebody other than ccs-queryd (such as less(1)) is opening /proc/ccs/policy/query interface, for such process doesn't write dummy decisions. Version 1.3 2006/11/11 First anniversary release. Fix 2006/11/13 @ Replace trust_domain with keep_domain. Since it was troublesome that there are two elements that can disable MAC (assigning a profile that doesn't enable MAC or registering domains with trust_domain directive), I removed trust_domain directive. Instead, I introduced keep_domain directive to not to transit domains unless a program registered with initializer directive is executed. This change has the following advantages. (1) Allows administrator use "enforce mode" for operations after login. Since it was difficult to know what commands and files are invoked and accessed in what sequences beforehand, we had to use trust_domain directive for such domain, allowing users invoke any commands and access any files in any sequence. But now, we can use keep_domain directive and assign a profile for "enforce mode" for such domain, forcing users invoke only allowed commands and access only allowed files in any sequence while these operations are kept under the control of "enforce mode". (2) Allows administrator determine easily whether the domain is under MAC or not because only the profile currently assigned to the domain determines it. (3) Saves total number of domains and memory. Fix 2006/11/22 @ Don't allow use of undefined profile. To avoid assigning undefined profile to domains by error, I added checks before assigning profiles to domains. Now, profiles have to be defined prior to assigning them to domains. Version 1.3.1 2006/12/08 Minor update release. Fix 2006/12/10 @ Allow pathname grouping. To reduce the labor of repeating '/\*' to allow access recursively, I introduced a macro 'path_group' to make group such pathnames. For example, you had to give like 4 /var/www/html/\* 4 /var/www/html/\*/\* 4 /var/www/html/\*/\*/\* 4 /var/www/html/\*/\*/\*/\* but now, you can give just 4 @WEB-CONTENTS if you give path_group WEB-CONTENTS /var/www/html/\* path_group WEB-CONTENTS /var/www/html/\*/\* path_group WEB-CONTENTS /var/www/html/\*/\*/\* path_group WEB-CONTENTS /var/www/html/\*/\*/\*/\* in the exception policy. This macro will be useful when grouping different directories. Fix 2006/12/15 @ Use structured pathnames instead for simple 'char *'. To reduce the cost of strcmp(), I changed the return value of SaveName() from 'const char *' to 'const struct path_info *'. This change will speed up PathMatchesToPattern() comparison. Fix 2006/12/19 @ Allow registering policy managers using domainnames. It was difficult to restrict programs that can update policies via /proc/ccs/ interfaces using pathnames of these programs, for these programs could be unintendedly invoked. Now, it became possible to restrict domains that can update policies via /proc/ccs/ interfaces as well as programs. By restricting using domainnames, it becomes easier to avoid unintended invocation. Fix 2006/12/22 @ Add initialize_domain,no_initizlize_domain,no_keep_domain To control domain transitions more strictly, initialize_domain,no_initizlize_domain,no_keep_domain directives were introduced. "initialize_domain /some/program" means jump to " /some/program" domain if /some/program is called from any domain. This is equivalent to conventional "initializer /some/program". "initialize_domain /some/program from some_domain" means jump to " /some/program" domain only if /some/program is called from "some_domain" domain. "no_initialize_domain /some/program" means don't jump to " /some/program" domain even if "initialize_domain /some/program" or "initialize_domain /some/program from some_domain" are given if /some/program is called from any domain. "no_initialize_domain /some/program from some_domain" means don't jump to " /some/program" domain even if "initialize_domain /some/program" or "initialize_domain /some/program from some_domain" are given if /some/program is called from "some_domain" domain. "keep_domain some_domain" means don't jump to child domain if any programs are called from "some_domain" domain. "keep_domain /some/program from some_domain" means don't jump to child domain only if /some/program is called from "some_domain" domain. "no_keep_domain some_domain" means jump to child domain even if "keep_domain /some/program" or "keep_domain /some/program from some_domain" are given if any programs are called from "some_domain" domain. "no_keep_domain /some/program from some_domain" means jump to child domain even if "keep_domain /some/program" or "keep_domain /some/program from some_domain" are given if /some/program is called from "some_domain" domain. "some_domain" can be just the last component of domainname. For example, giving "/bin/mail" as "some_domain" matches to all domains whose domainname ends with "/bin/mail". Fix 2007/01/19 @ Allow reuse of memory allocated for domain policy. Regarding domain policy, unlike other policies, didn't have "is_deleted" flag and new memory were allocated if the deleted entries are given again. But to allow administrators switch domain policy periodically, I introduced "is_deleted" flag. Writing "some_domain" to /proc/ccs/policy/domain_policy creates "some_domain" using new memory if it didn't exist. Writing "select some_domain" doesn't create "some_domain" if it didn't exist. Writing "delete some_domain" deletes "some_domain" but does not delete entries in "some_domain". Writing "undelete some_domain" undeletes "some_domain" if it was deleted by "delete some_domain". Fix 2007/01/22 @ Allow getting already deleted pathnames. To allow getting pathnames that are already deleted, I removed (IS_ROOT(dentry) || !d_unhashed(dentry)) check. Fix 2007/01/26 @ Limit string length to 4000. I was using PAGE_SIZE (4096 in many environments) as the max length of any string data. But for environments that have larger PAGE_SIZE, doing memset(ptr, 0, PAGE_SIZE) everytime is too wasteful. Fix 2007/01/29 @ Add garbage collector for domain policy. Writing "some_domain" to /proc/ccs/policy/domain_policy creates "some_domain" using new memory only if some process is staying at that deleted domain. If no process is staying at that deleted domain, "some_domain" is undeleted with all ACLs deleted. Version 1.3.2 2007/02/14 Usability enhancement release. Fix 2007/02/20 @ Allow address grouping. To reduce the labor of repeating similar IPv4/IPv6 addresses, I introduced a macro 'address_group' to make group such addresses. For example, you had to give like allow_network TCP accept 10.0.0.0-10.255.255.255 1024-65535 allow_network TCP accept 172.16.0.0-172.31.255.255 1024-65535 allow_network TCP accept 192.168.0.0-192.168.255.255 1024-65535 but now, you can give just allow_network TCP accept @localnet 1024-65535 if you give address_group localnet 10.0.0.0-10.255.255.255 address_group localnet 172.16.0.0-172.31.255.255 address_group localnet 192.168.0.0-192.168.255.255 in the exception policy. Fix 2007/03/03 @ Remove obsolete functions. @ Add some hooks. Read permission check is done if open_exec() is called from search_binary_handler(). Read permission check is not done if open_exec() is called from do_execve(), instead, execute permission check is done at search_binary_handler_with_transition(). I moved the location of calling CheckCapabilityACL() and CheckMountPermission() from sys_mount() to do_mount(). Fix 2007/03/07 @ Use 'unsigned int' for sscanf(). I compiled SYAORAN fs on x86_64 environment and found the compiler showing warning messages about size of data types. Since size of data types may mismatch for sscanf(), I replaced some types with 'unsigned int'. Version 1.4 2007/04/01 x86_64 support release. Fix 2007/04/18 @ Change argv[0] checking rule. I was comparing the basename of symbolic link's pathname and argv[0]. Since execute permission check and domain transition are done based on realpath while argv[0] check is done based on the symlink's pathname and argv[0], this specification will allow attackers behave as /bin/cat in the domain of /bin/ls if "/bin/ls and /bin/cat are links to /sbin/busybox" and "the attacker is permitted to create a symlink named ~/cat that points to /bin/ls" and "the attacker is permitted to run /bin/ls". So, I changed to compare the basename of realpath and argv[0]. Also, I moved the location to compare before processing "aggregator" directive so that "aggregator /tmp/logrotate.\?\?\?\?\?\? /tmp/logrotate.tmp" won't cause the mismatch of the basename of realpath and argv[0]. If /bin/ls is a symlink to /sbin/busybox, then creating a symlink named ~/cat that points to /bin/ls and executing ~/cat won't work as expected because permission check and domain transition are done using /sbin/busybox (realpath of /bin/ls) and will be rejected since the administrator won't grant "1 /sbin/busybox". Fix 2007/05/07 @ Support pathname subtraction. There was no way to exclude specific pathnames when granting permissions using wildcards. There would be a need to exclude specific files and directories. I introduced "\-" as subtraction operator. "A\-B" means "A" other than "B". "A\-B\-C" means "A" other than "B" and "C". "A\-B\-C\-D" means "A" other than "B" and "C" and "D". "A", "B", "C", "D" may contain wildcards. An example usage is "/home/\*/\*\-.ssh/\*", which means "/home/\*/\*/\*" other than "/home/\*/.ssh/\*". "A" should contain wildcards because subtraction from constants (e.g. "/usr\-usr/" or "/usr\-home/") is meaningless. Don't try "A\-B\+C" because "\+" is not addition operator. Fix 2007/05/24 @ Fix autobind hook. The location to call SAKURA_MayAutobind() in net/ipv4/udp.c and net/ipv6/udp.c were wrong. Fix 2007/06/03 @ Add a space in MakeMountOptions(). I forgot to add a space after "atime" and "noatime". Version 1.4.1 2007/06/05 Minor update release. Fix 2007/07/04 @ Fix ReadAddressGroupPolicy() bug. ReadAddressGroupPolicy() fails if both "path_group" and "address_group" are used because I forgot to set "head->read_var1 = NULL". Fix 2007/07/10 @ Add compat_sys_stime() hook. Some of 64bit kernels support compat_sys_stime() but permission check was missing. Version 1.4.2 2007/07/13 Bug fix release. Fix 2007/08/06 @ Remove mount-flags manipulation. Until now, administrator is permitted to turn on/off specific mount options regardless of mount options passed to kernel. I removed this feature because "exact option matching" sounds better than "automatic option enabler/disabler". @ Remove /proc/ccs/info/mapping . I removed /proc/ccs/info/mapping because nobody seems to use this feature. @ Call external policy loader automatically. Until now, users had to add init=/.init parameter to load policy before /sbin/init starts. I inserted call_usermodehelper() to call external policy loader when execve("/sbin/init") is requested and external policy loader exists. This change will remove init=/.init parameter from most environment, although call_usermodehelper() can't handle interactive operations. @ Move external policy loader from /.init to /sbin/ccs-init . Installing programs in / directory is not good for packaging. Fix 2007/08/13 @ Update external policy loader. It turned out that /sbin/ccs-init invoked via call_usermodehelper() can handle interactive operations by opening /dev/console . Now, there is no difference between init=/sbin/ccs-init and call_usermodehelper("/sbin/ccs-init"), and users no longer need to add init=/sbin/ccs-init parameter to load policy before /sbin/init starts. Fix 2007/08/14 @ Update recvmsg() hooks. Until now, it was impossible to apply network access control for incoming UDP and RAW packets if they are brought to userland using read() or recvmsg() with NULL address because address buffer is NULL. I moved hooks from sock_recvmsg() to skb_recv_datagram() so that network access control for incoming UDP and RAW packets always work. Fix 2007/08/16 @ Return appropriate error code for CheckMountPermission(). I was returning -EPERM if something is wrong with CheckMountPermission(). But SELinux determines whether selinuxfs is supported by kernel based on whether error code is -ENODEV or not. So I stopped returning -EPERM unconditionally. Fix 2007/08/17 @ Remove initializer directive. Use "initialize_domain" instrad of "initializer". Fix 2007/08/21 @ Fix "allow_argv0 ... if if ..." bug. It was impossible to use a word "if" to the second argument of allow_argv0 if condition part is used. Fix 2007/08/24 @ Move /proc/ccs/\*/\* to /proc/ccs/\* . Some pathnames for /proc/ccs/ interface were changed. Fix 2007/09/05 @ Drop MSG_PEEK'ed message before skb_free_datagram(). I need to remove head message from unwanted source from socket's receive queue so that the caller can pick up next message from wanted source with MSG_PEEK flags. Version 1.5.0 2007/09/20 Usability enhancement release. Fix 2007/09/27 @ Avoid eating memory after quota exceeded. Although ACL entries in a domain won't be added if the domain's quota has exceeded, SaveName() in AddFileACL() is called anyway. This caused unneeded memory consumption. Now, quota checking is done before getting domain_acl_lock lock. This may exceed quota by one or two entries, but that won't matter. Fix 2007/10/16 @ Add environment variable check. There are environment variables that may cause dangerous behavior like LD_\* . So I introduced 'allow_env' directive that allows specified environment variable inherited to next domain. Unlike other permissions, this check is done at execve() time using next domain's ACL information. To manage commonly inherited environments like PATH , you can use 'allow_env' directive in exception policy to globally grant specified environment variable. Fix 2007/11/05 @ Replace semaphore with mutex. I replaced semaphore with mutex. @ Add missing down() in AddReservedEntry(). Mutex debugging capability told me that I had forgotten to call down() since TOMOYO version 1.3.2 . This function is not called by learning mode, so the semaphore's counter will not overflow for normal usage. Fix 2005/11/27 @ Fix ReadTable() truncation bug. "snprintf(str, size, format, ...) >= size" means truncated. But I was checking for "snprintf(str, size, format, ...) > size". As a result, some entries might be dumped without '\n'. @ Purge direct "->prev"/"->next" manipulation. All list manipulations use "struct list_head" or "struct list1_head". "struct list1_head" doesn't have "->prev" member to save memory usage. Fix 2007/11/29 @ Add missing semaphore in GetEXE(). mm->mmap_sem was missing. Fix 2007/12/17 @ Remove unused EXPORT_SYMBOL(). Mark some functions static. Fix 2007/12/18 @ Fix AddMountACL() rejection bug. To my surprise, "mount --bind source dest" accepts not only "both source and dest are directory" but also "both source and dest are non-directory". I was rejecting if dest is not a derectory in AddMountACL().