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 "<NULL>" in AddMountACL().

      VMware mounts vmware-hgfs with NULL device name.
      So I mapped NULL device name to "<NULL>".

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.
