Notes for TOMOYO Linux project

This is a handy Mandatory Access Control patch for Linux kernels.
This patch is released under the GPLv2.

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.

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 "zero or more repetitions of characters
      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 zero or more repetitions of characters until next '/'.
      Now, "\*" matches zero or more repetitions of characters.

      Until now, it was impossible to use patterns like "\$00"
      because "\$" matched one or more repetitions of digits until next
      non digit character.
      Now, "\$" matches one or more repetitions of 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 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 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 directive 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 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 "<kernel> /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 "<kernel> /some/program" domain only if /some/program is
      called from "some_domain" domain.

      "no_initialize_domain /some/program" means
      don't jump to "<kernel> /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 "<kernel> /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
      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" instead 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 directory in AddMountACL().

    @ Change log format.

      Profile number and mode is added in audit logs.

Fix 2008/01/03

    @ Change directive for file's read/write/execute permission.

      Directives for file's read/write/execute permissions were
      4/2/1 respectively. But for easier understanding, they are now
      replaced by read/write/execute (e.g. "allow_read" instead of "4").
      But for easier inputting, 4/2/1 are still accepted instead of
      allow_read/allow_write/allow_execute respectively.

    @ Change internal data structure.

      Since I don't have more than 16 types of file permissions,
      I combined them using bit-fields.

      Each entry had a field for conditional permission support.
      But since this field is unlikely used, I separated the field from
      common part.

      These changes will reduce memory used by policy.

Fix 2008/01/15

    @ Add ptrace() hook.

      To prevent attackers from controlling important processes using
      ptrace(), I added a hook for ptrace().
      Most programs (except strace(1) and gdb(1)) won't use ptrace(2).

    @ Fix sleep condition check in CheckSocketRecvDatagramPermission().

      It seems that correct method to use is in_atomic()
      rather than in_interrupt() because in_atomic() returns nonzero
      whenever scheduling is not allowed.

Fix 2008/02/05

    @ Use find_task_by_vpid() instead of find_task_by_pid().

      Kernel 2.6.24 introduced PID namespace.
      To search PID given from userland, the kernel needs to use
      find_task_by_vpid() instead of find_task_by_pid().

Fix 2008/02/14

    @ Add execve() parameter checking.

      Until now, it was impossible to check argv[] and envp[] parameters
      passed to execve().
      I expanded conditional permission syntax so that
      { argc, envc, argv[] , envp[] } parameters can be checked if needed.
      This will allow administrator permit execution of /bin/sh only when
      /bin/sh is invoked in the form of "/bin/sh -c" and environment variable
      HOME is set by specifying

        allow_execute /bin/sh if exec.argv[1]="-c" exec.envp["HOME"]!=NULL

      in the policy.
      This extension will make exploit codes difficult to start /bin/sh because
      they unlikely set up environment variables and unlikely specify "-c"
      option when invoking /bin/sh , whereas proper functions likely set up
      environment variables and likely specify "-c" option.

Fix 2008/02/18

    @ Add process state checking.

      Until now, it was impossible to change ACL without executing program.
      I added three variables for performing stateful checking within a domain.
      You can set current process's state like:

        allow_network TCP accept @TRUSTED_HOSTS 1024-65535 ; set task.state[0]=1
        allow_network TCP accept @UNTRUSTED_HOSTS 1024-65535 ; set task.state[0]=0

      and you can use the state like

        allow_read /path/to/important/file if task.state[0]=1

      in the policy.
      The state changes when the request was granted by the MAC's policy,
      so please be careful with situations where the state has changed
      successfully but the request was not processed because of other reasons
      (e.g. out of memory).

Fix 2008/02/26

    @ Support /proc/ccs/ access by non-root user.

      Until now, only root user can access /proc/ccs/ interface.
      But to permit /proc/ccs/ access by non-root user so that it won't require
      ssh login by root user when administrating from remote host,
      I made "(current->uid == 0 && current->euid == 0)" requirement optional.
      If this requirement is disabled, only "conventional DAC permission
      checks" and "/proc/ccs/manager checks" are used.

Fix 2008/02/29

    @ Add sleep_on_violation feature.

      Some exploit codes (e.g. trans2open for Samba) continue running
      until it achieves the purpose of the exploit code (e.g. invoke /bin/sh).

      If such code is injected due to buffer overflow but the kernel
      rejects the request, it triggers infinite "Permission denied" loop.
      As a result, the CPU usage becomes 100% and gives bad effects to
      the rest of processes.
      This is a side effect of rejecting the request from the exploit code
      which wouldn't happen if the request from the exploit code was granted.

      To avoid such CPU consumption, I added a penalty that forcibly
      sleeps for specified period when a request is rejected.

      This penalty doesn't work if the exploit code does nothing but
      continue running, but I think most exploit code's purpose is
      to start some program rather than to slow down the target system.

    @ Add alt_exec feature.

      Since TOMOYO Linux's approach is "know all essential requests in advance
      and create policy that permits only them", you can regard anomalous
      requests as attacks (if you want to do so).

      Common MAC implementations merely reject requests that violate policy.
      But I added a special handler for execve() to TOMOYO Linux.

      This handler is triggered when a process requested to execute a program
      but the request was rejected by the policy.
      This handler executes a program specified by the administrator
      instead of a program requested by the process.

      Most attackers attempt to execute /bin/sh to start something malicious.
      Attackers execute an exploit code using buffer overflow vulnerability
      to steal control of a process. But this handler can get back control
      if an exploit code requests execve() that is not permitted by policy.

      By default, this handler does nothing (i.e. merely reject execve()
      request). You can specify any program to start what you want to do.

      You can redirect attackers to somewhere else (e.g. honey pot).
      This makes it possible to act your Linux box as an on-demand honey pot
      while keeping regular services for your usage.

      You can collect information of the attacker (e.g. IP address) and
      update firewall configuration.

      You can silently terminate a process who requested execve()
      that is not permitted by policy.

Fix 2008/03/03

    @ Add "force_alt_exec" directive.

      To be able to fully utilize "alt_exec" feature,
      I added "force_alt_exec" directive so that
      all execute requests are replaced by the execute request of a program
      specified by alt_exec feature.

      If this directive is specified for a domain, the domain no longer
      executes any programs regardless of the mode of file access control
      (i.e. the domain won't execute even if MAC_FOR_FILE=0 ).
      Instead, the domain executes the program specified by alt_exec feature
      and the program specified by alt_exec feature validates the execute
      request and executes it if it is appropriate to execute.

      If you can tolerate that there is no chance to return an error code
      to the caller to tell the execute request was rejected,
      this is more flexible approach than in-kernel execve() parameter
      checking because we can do argv[] and envp[] checking easily.

Fix 2008/03/04

    @ Use string for access control mode.

      An integer expression for access control mode sometimes confuses
      administrators because profile number is also an integer expression.
      To avoid confusion between profile number and access control mode,
      I introduced a string expression for access control mode.

        Modes which take an integer between 0 and 3.

          0 -> disabled
          1 -> learning
          2 -> permissive
          3 -> enforcing

        Modes which take 0 or 1.

          0 -> disabled
          1 -> enabled

Fix 2008/03/10

    @ Rename "force_alt_exec" directive to "execute_handler".

      To be able to use different programs for validating execve() parameters,
      I moved the location to specify the program's pathname from profile
      to domain policy.

      The "execute_handler" directive takes one pathname which is
      invoked whenever execve() request is issued. Thus, any "allow_execute"
      directives in a domain with "execute_handler" are ignored.
      This directive is designed for validating expected/desirable execve()
      requests in userspace, although there is no way to tell the caller
      that the execve() request was rejected.

    @ Rename "alt_exec" directive to "denied_execute_handler".

      The "denied_execute_handler" directive takes one pathname which is
      invoked only when execve() request was rejected. In other words,
      this program is invoked only when the following conditions are met.

        (1) None of "allow_execute" directives in the domain matched.
        (2) The execve() request was rejected in enforcing mode.
        (3) "execute_handler" directive is not used by the domain.

      This directive is designed for handling unexpected/undesirable execve()
      requests, to redirect the process issuing such requests to somewhere.

Fix 2008/03/18

    @ Fix wrong/redundant locks in pre-vfs functions.

      lock_kernel()/unlock_kernel() in pre_vfs_rename() were redundant for
      2.6 kernels.

      Locking order in pre_vfs_link() and pre_vfs_unlink() for 2.4 kernels
      after 2.4.33 were different from before 2.4.32 .

Fix 2008/03/28

    @ Disable execute handler loop.

      To be able to use "execute_handler" in a "keep_domain" domain,
      ignore "execute_handler" and "denied_execute_handler" directives
      if the current process is executing programs specified by
      "execute_handler" or "denied_execute_handler" directive.

      This exception is needed to avoid infinite execute handler loop.
      If a domain has both "keep_domain" and "execute_handler",
      any execute request by that domain is handled by an execute handler,
      and the execute handler attempts to process original execute request.
      But the original execute request is handled by the same execute handler
      unless the execute handler ignores "execute_handler".

    @ Update coding style.

      I rewrote the code to pass scripts/checkpatch.pl as much as possible.
      Function names were changed to use only lower letters.

Version 1.6.0 2008/04/01   Feature enhancement release.

Fix 2008/04/14

    @ Fix "Compilation failures" and "Initialization ordering bugs"
      with kernels before 2.4.30/2.6.11 .

      2.6 kernels before 2.6.9 didn't have include/linux/hardirq.h ,
      resulting compilation error at #include <linux/hardirq.h> .
      I added #elif condition.

      CentOS 4.6's 2.6.9 kernel calls do_execve() before initialization of
      ccs_alloc(), resulting NULL pointer dereference.
      I changed __initcall to core_initcall.

      CentOS 4.6's 2.6.9 kernel backported kzalloc() from 2.6.14 ,
      resulting compilation error at kzalloc().
      I modified prototype of kzalloc().

Fix 2008/04/20

    @ Fix "Compilation failures" with kernels before 2.4.30/2.6.11 .

      Turbolinux 10 Server's 2.6.8 kernel backported kzalloc() as an inlined
      function, resulting compilation error at kzalloc().
      I converted kzalloc() from an inlined function into a macro.

Fix 2008/04/21

    @ Add workaround for gcc 3.2.2's inline bug.

      RedHat Linux 9's gcc 3.2.2 generated a bad code
         if ((var_of_u8 & 0x000000BF) & 0x80000000) { }
      where the expected code is
         if ((var_of_u8 & 0xBF) & 0x80) { }
      when embedding ccs_acl_type2() into print_entry(),
      resulting runtime BUG().
      I added the expected code explicitly as a workaround.

Fix 2008/05/06

    @ Add memory quota.

      1.5.x returns -ENOMEM when FindNextDomain() failed to create a new
      domain, but I forgot to return -ENOMEM when find_next_domain() failed to
      create a new domain.

      A domain is automatically created by find_next_domain() only if
      the domain for the requested program doesn't exist.
      This behavior is for the administrator's convenience.
      The administrator needn't to know how many domains are needed for running
      the whole programs in the system beforehand when developing the policy.
      But the administrator does not want the kernel to reject execution of the
      requested program when developing the policy.

      So, I think it is better to grant execution of programs even if
      find_next_domain() failed to create a new domain than reject execution.
      Thus, I decided not to return -ENOMEM when find_next_domain() failed to
      create a new domain. This exception breaks the domain transition rules,
      so I print "transition_failed" warning in /proc/ccs/domain_policy
      when this exception happened.

      Also, to prevent the system from being halted by unexpectedly allocating
      all kernel memory for the policy, I added memory quota.
      This quota is configurable via /proc/ccs/meminfo like

        echo Shared:  1048576 > /proc/ccs/meminfo
        echo Private: 1048576 > /proc/ccs/meminfo

Version 1.6.1 2008/05/10   Bug fix release.

Fix 2008/06/04

    @ Check open mode of /proc/ccs/ interface.

      It turned out that I can avoid allocating memory for reading if
      FMODE_READ is not set and memory for writing if FMODE_WRITE is not set.

    @ Wait for completion of /sbin/ccs-init .

      Since 2.4 kernel's call_usermodehelper() can't wait for termination of
      the executed program, I was using the close() request of
      /proc/ccs/meminfo to indicate that loading policy has finished.
      But since /proc/ccs/meminfo could be accessed for setting memory quota
      by /etc/ccs/ccs-post-init , I stopped using the close() request.
      The policy loader no longer need to access /proc/ccs/meminfo to notify
      the kernel that loading policy has finished.

Fix 2008/06/05

    @ Fix realpath for pipes and sockets.

      Kernel 2.6.22 and later use different method for calculating d_path().
      Since fs/realpath.c didn't notice the change, the realpath of pipes
      appeared as "pipe:" rather than "pipe:[\$]" when they are opened via
      /proc/PID/fd/ directory.

    @ Add process's information into /proc/ccs/query .

      While /proc/ccs/grant_log and /proc/ccs/reject_log contain process's
      information, /proc/ccs/query doesn't contain it.
      To be able to utilize ccs-queryd and ccs-notifyd more, I added it into
      /proc/ccs/query .

Fix 2008/06/10

    @ Allow using patterns for globally readable files.

      To allow users specify locale specific files to globally readable files,
      I relaxed checking in update_globally_readable_entry().

Fix 2008/06/11

    @ Remove ALLOW_ENFORCE_GRACE parameter.

      Since unexpected requests caused by doing software updates can happen
      in all profiles, users likely have to write ALLOW_ENFORCE_GRACE=enabled
      to all profiles. And it makes meaningless to allow users to selectively
      enable specific profile's ALLOW_ENFORCE_GRACE parameter.
      So, I removed ALLOW_ENFORCE_GRACE parameter.
      Now, the system behaves as if ALLOW_ENFORCE_GRACE=enabled is specified.
      The behavior of "delayed enforcing" mode is defined in the following
      order.

      (1) The requests are rejected immediately if nobody is opening
          /proc/ccs/query interface.
      (2) The requests will be rejected in 10 seconds if somebody other than
          ccs-queryd (such as less(1)) is opening /proc/ccs/query interface,
          for such process doesn't write dummy decisions.

Fix 2008/06/22

    @ Pass escaped pathname to audit_execute_handler_log().

      I was passing unescaped pathname to audit_execute_handler_log()
      which causes /proc/ccs/grant_log contain whitespace characters
      if execute handler's pathname contains whitespace characters.

Fix 2008/06/25

    @ Return 0 when ccs_may_umount() succeeds.

      I forgot to clear error value in ccs_may_umount() when the requested
      directory didn't match "deny_unmount" directive. As a result, any umount()
      request with RESTRICT_UNMOUNT=enforcing returned -EPERM error.

Version 1.6.2 2008/06/25   Usability enhancement release.

Fix 2008/07/01

    @ Fix "Compilation failure" with 2.4.20 kernel.

      RedHat Linux 9's 2.4.20 kernel backported O(1) scheduler patch,
      resulting compilation error at ccs_load_policy().
      I added defined(TASK_DEAD) check.

Fix 2008/07/08

    @ Don't check permissions if vfsmount is NULL.

      Some filesystems (e.g. unionfs) pass NULL vfsmount.
      I changed fs/tomoyo_file.c not to try to calculate pathnames
      if vfsmount is NULL.

Version 1.6.3 2008/07/15   Bug fix release.

Fix 2008/08/21

    @ Add workaround for gcc 4.3's bug.

      In some environments, fs/tomoyo_network.c could not be compiled
      because of gcc 4.3's bug.
      I modified save_ipv6_address() to use "integer literal" value
      instead for "static const u8" variable.

    @ Change prototypes of some functions.

      To support 2.6.27 kernels, I replaced "struct nameidata" with
      "struct path" for some functions.

    @ Detect distributor specific patches automatically.

      Since kernels with AppArmor patch applied is increasing,
      I introduced a mechanism which determines whether specific patches
      are applied or not, based on "#define" directives in the patches.

Fix 2008/08/29

    @ Remove "-ccs" suffix from Makefile's EXTRAVERSION.

      To reduce conflicts on Makefile's EXTRAVERSION,
      I removed "-ccs" suffix from ccs-patch-2.\*.diff .
      Those who build kernels without using specs/build-\*.sh ,
      please edit EXTRAVERSION tag manually so that original kernels
      will not be overwritten by TOMOYO Linux kernels.

Version 1.6.4 2008/09/03   Minor update release.

Fix 2008/09/09

    @ Add "try again" response to "delayed enforcing" mode.

      To be able to handle pathname changes caused by software updates,
      "delayed enforcing" mode was introduced. It allows administrator to
      grant access requests which are about to be rejected by the kernel.

      To be able to handle pathname changes caused by software updates better,
      I introduced "try again" response. As "delayed enforcing" mode sleeps
      a process which violated policy, administrator can update policy while
      the process is sleeping. This "try again" response allows administrator
      to restart policy checks from the beginning after updating policy.

Fix 2008/09/11

    @ Remember whether the process is allowed to write to /proc/ccs/ interface.

      Since programs for manipulating policy (e.g. ccs-queryd ) are installed
      in the form of RPM/DEB packages, these programs lose the original
      pathnames when they are updated by the package manager. The package
      manager renames these programs before deleting these programs so that
      the package manager can rollback the operation.
      This causes a problem when the programs are listed into /proc/ccs/manager
      using pathnames, as the programs will no longer be allowed to write to
      /proc/ccs/ interface while the process of old version of the program is
      alive.

      To solve this problem, I modified to remember the fact that the process
      is once allowed to write to /proc/ccs/ interface until the process
      attempts to execute a different program.
      This change makes it impossible to revoke permission to write to
      /proc/ccs/ interface without killing the process, but it will be better
      than nonfunctioning ccs-queryd program.

Fix 2008/09/19

    @ Allow selecting a domain by PID.

      Sometimes we want to know what ACLs are given to specific PID, but
      finding a domainname for that PID from /proc/ccs/.process_status and
      reading ACLs from /proc/ccs/domain_policy by the domainname is very slow.
      Thus, I modified /proc/ccs/domain_policy to allow selecting a domain by
      PID. For example, to read domain ACL of current process from bash,
      run as follows.

      # exec 100<>/proc/ccs/domain_policy
      # echo select pid=$$ >&100
      # while read -u 100; do echo $REPLY; done

      If a domain is once selected by PID, reading /proc/ccs/domain_policy will
      print only that domain if that PID exists or print nothing otherwise.

    @ Disallow concurrent /proc/ccs/ access using the same file descriptor.

      Until now, one process can read() from /proc/ccs/ while other process
      that shares the file descriptor can write() to /proc/ccs/ .
      But to implement "Allow selecting a domain by PID" feature, I disabled
      concurrent read()/write() because the feature need to modify read buffer
      while writing.

Fix 2008/10/01

    @ Add retry counter into /proc/ccs/query .

      To be able to handle some of queries from /proc/ccs/query without user's
      interaction, I added retry counter for avoiding infinite loop caused by
      "try again" response.

Fix 2008/10/07

    @ Don't transit to new domain until do_execve() succeeds.

      Until now, a process's domain was updated to new domain which the process
      will belong to before do_execve() succeeds so that the kernel can do
      permission checks for interpreters and environment variables based on
      new domain. But this caused a subtle problem when other process sends
      signals to the process, for the process returns to old domain if
      do_execve() failed.

      So, I modified to pass new domain to functions so that I can avoid
      modifying a process's domain before do_execve() succeeds.

    @ Use old task state for audit logs.

      Until now, audit logs were generated using the task state after
      processing "; set task.state" part. But to generate accurate logs,
      I modified to save the task state before processing "; set task.state"
      part and use the saved state for audit logs.

    @ Use a structure for passing parameters.

      As the number of parameters is increasing, I modified to use a structure
      for passing parameters.

Fix 2008/10/11

    @ Remove domain_acl_lock mutex.

      I noticed that I don't need to keep all functions that modify an ACL of
      a domain mutually exclusive. Since each functions handles different type
      of ACL, locking is needed only when they append an ACL to a domain.
      So, I modified to use local locks.

Fix 2008/10/14

    @ Fix ccs_check_condition() bug.

      Due to a bug in ccs_check_condition(), it was impossible to use
      task.state[0] task.state[1] task.state[2] inside condition part
      if the ACL does not treat a pathname. For example, an ACL like

        allow_network TCP connect @HTTP_SERVERS 80 if task.state[0]=100

      didn't work.

Fix 2008/10/15

    @ Show process information in /proc/ccs/.process_status .

      To be able to determine a process's type, I added a command "info PID"
      which returns process information of the specified PID in
      "PID manager=\* execute_handler=\* state[0]=\$ state[1]=\$ state[2]=\$"
      format.

Fix 2008/10/20

    @ Use rcu_dereference() when walking the list.

      I was using "dependency ordering" for appending an element to a list
      without asking the reader to take a lock. But "dependency ordering"
      is not respected by DEC Alpha or by some aggressive value-speculation
      compiler optimizations.

      On such environment, use of "dependency ordering" can lead to system
      crash because the reader might read uninitialized value of newly
      appended element.

      To prevent the reader from reading uninitialized value of newly appended
      element, I inserted rcu_dereference() when walking the list.

Fix 2008/11/04

    @ Use sys_getpid() instead for current->pid.

      Kernel 2.6.24 introduced PID namespace.

      To compare PID given from userland, I can't use current->pid.
      So, I modified to use sys_getpid() instead for current->pid.

      I modified to use task_tgid_nr_ns() for 2.6.25 and later instead for
      current->tgid when checking /proc/self/ in get_absolute_path().

Fix 2008/11/07

    @ Fix is_alphabet_char().

      is_alphabet_char() should match 'A' - 'Z' and 'a' - 'z',
      but was matching from 'A' - 'F' and 'a' - 'f'.

    @ Add /proc/ccs/.execute_handler .

      Process information became visible to userspace by
      "Show process information in /proc/ccs/.process_status" feature.
      However, programs specified by execute_handler directive may run as
      non root user, making it impossible to see process information.

      So, I added a new interface that allows execute handler processes
      to see process information. The content of /proc/ccs/.execute_handler is
      identical to /proc/ccs/.process_status .

Version 1.6.5 2008/11/11   Third anniversary release.

Fix 2008/12/01

    @ Introduce "task.type=execute_handler" condition.

      The execute_handler directive is very very powerful. You can use this
      directive to do anything you want to do (e.g. logging and validating and
      modifying command line parameters and environment variables, opening and
      closing and redirecting files, creating pipes to implement antivirus and
      spam filtering, deploying a DMZ between the ssh daemon and the login
      shells).

      To be able to use this directive in a domain with keep_domain directive
      while limiting access to resources needed for such purposes to only
      programs invoked as an execute handler process, I added a new condition.

      In learning mode, "if task.type=execute_handler" condition part will be
      automatically added for requests issued by an execute_handler process.

    @ Introduce file's type and permissions as conditions.

      To be able to limit file types a process can access, I added
      new conditions for checking file's type and permissions.
      For example,

        allow_read /etc/fstab if path1.type=file path1.perm=0644

      will allow opening /etc/fstab for reading only if /etc/fstab is a regular
      file and it's permission is 0644, and

        allow_write /dev/null if path1.type=char path1.dev_major=1 path1.dev_minor=3

      will allow opening /dev/null for writing only if /dev/null is a character
      device file with major=1 and minor=3 attributes.

    @ Add memory quota for temporary memory used for auditing.

      Although there are MAX_GRANT_LOG and MAX_REJECT_LOG parameters
      which limit the number of entries for audit logs so that we can avoid
      memory consumption by audit logs, it would be more convenient if we can
      also limit the size in bytes.
      Thus, I added a new quota line.

        echo Dynamic: 1048576 > /proc/ccs/meminfo

      This quota is not applied to temporary memory used for permission checks.

Fix 2008/12/09

    @ Fix ccs_can_save_audit_log() checks.

      Due to incorrect statement "if (ccs_can_save_audit_log() < 0)"
      while ccs_can_save_audit_log() is boolean, MAX_GRANT_LOG and
      MAX_REJECT_LOG were not working.

      This bug will trigger OOM killer if /usr/sbin/ccs-auditd is not working.

Fix 2008/12/24

    @ Add "ccs_" prefix.

      To be able to tell whether a symbol is TOMOYO Linux related or not,
      I added "ccs_" prefix as much as possible.

    @ Fix ccs_check_flags() error message.

      I meant to print SYAORAN-ERROR: message when error == -EPERM,
      but I was printing it when error == 0 since 1.6.0 .

Fix 2009/01/05

    @ Use kmap_atomic()/kunmap_atomic() for reading "struct linux_binprm".

      As remove_arg_zero() uses kmap_atomic(KM_USER0), I modified to use
      kmap_atomic(KM_USER0) rather than kmap().

Fix 2009/01/28

    @ Fix "allow_read" + "allow_write" != "allow_read/write" problem.

      Since 1.6.0 , due to a bug in ccs_update_single_path_acl(),
      appending "allow_read/write" entry didn't update internal "allow_read"
      and "allow_write" entries. As a result, attempt to open(O_RDWR) succeeds
      but open(O_RDONLY) and open(O_WRONLY) fail.

      Workaround is to write an entry twice when newly appending that entry.
      If written twice, internal "allow_read" and "allow_write" entries
      are updated.

Fix 2009/02/26

    @ Fix profile read error.

      Incorrect profiles were shown in /proc/ccs/profile
      if either CONFIG_SAKURA or CONFIG_TOMOYO is disabled.

Fix 2009/03/02

    @ Undelete CONFIG_TOMOYO_AUDIT option.

      While HDD-less systems can use profiles with MAX_GRANT_LOG=0 and
      MAX_REJECT_LOG=0 , I undeleted CONFIG_TOMOYO_AUDIT option for saving
      memory used for /proc/ccs/grant_log and /proc/ccs/reject_log interfaces.

Fix 2009/03/13

    @ Show only profile entry names ever specified.

      Even if an administrator specifies only COMMENT= and MAC_FOR_FILE=
      entries for /proc/ccs/profile , all available profile entries are shown.
      This was designed to help administrators to know what entries are
      available, but sometimes makes administrators feel noisy because of
      entries showing default values.

      Thus, I modified to show only profile entry names ever specified.

Fix 2009/03/18

    @ Add MAC_FOR_IOCTL functionality.

      To be able to restrict ioctl() requests, I added MAC_FOR_IOCTL
      functionality.

      This functionality requires modification of ccs-patch-\*.diff .

    @ Use better name for socket's pathname.

      Until now, socket's pathname was represented as "socket:[\$]" format
      where \$ is inode's number. But inode's number is useless for name based
      access control. Therefore, I modified to represent socket's pathname as
      "socket:[family=\$:type=\$:protocol=\$]" format.

      This will help administrator to control ioctl() against sockets more
      precisely.

    @ Fix misplaced ccs_capable() call.  (only 2.6.8-\* and 2.6.9-\*)

      Location to insert ccs_capable(TOMOYO_SYS_IOCTL) in sys_ioctl() was
      wrong since version 1.1 .

    @ Insert ccs_check_ioctl_permission() call.

      To make MAC_FOR_IOCTL functionality working, I inserted
      ccs_check_ioctl_permission() call into ccs-patch-\*.diff .

Fix 2009/03/23

    @ Move sysctl()'s check from ccs-patch-\*.diff to fs/tomoyo_file.c .

      Since try_parse_table() in kernel/sysctl.c is almost identical between
      all versions, I moved that function to fs/tomoyo_file.c .

    @ Relocate definitions and functions.

      To reduce exposed symbols, I relocated some definitions and functions.

Fix 2009/03/24

    @ Add CONFIG_TOMOYO_BUILTIN_INITIALIZERS option.

      Some systems don't have /sbin/modprobe and /sbin/hotplug .
      Thus, I made these pathnames configurable.

Version 1.6.7 2009/04/01   Feature enhancement release.

Fix 2009/04/06

    @ Drop "undelete domain" command.

      I added "undelete domain" command on 2007/01/19, but never used by policy
      management tools. The garbage collector I added on 2007/01/29 will
      automatically reuse memory and allow administrators switch domain policy
      periodically, provided that the administrator kills processes in old
      domains before recreating new domains with the same domainnames.

      Thus, I dropped "undelete domain" command.

    @ Escape invalid characters in ccs_check_mount_permission2().

      ccs_check_mount_permission2() was passing unencoded strings to printk()
      and ccs_update_mount_acl() and ccs_check_supervisor(). This may cause
      /proc/ccs/system_policy and /proc/ccs/query to contain invalid
      characters within a string.

Fix 2009/04/07

    @ Fix IPv4's "address_group" handling error.

      Since 1.6.5 , due to lack of ntohl() (byte order conversion) in
      ccs_update_address_group_entry(), "address_group" with IPv4 address was
      not working.

      This problem happens on little endian platforms (e.g. x86).

Fix 2009/05/08

    @ Add condition for symlink's target pathname.

      Until now, "allow_symlink" keyword allows creation of a symlink but does
      not check the symlink's target. Usually it is no problem because
      permission checks are done using dereferenced pathname. But in some
      cases, we should restrict the symlink's target. For example,
      "ln -s .htpasswd /var/www/html/readme.html" by CGI program should be
      blocked because we will allow Apache to read both
      /var/www/html/readme.html and /var/www/html/.htpasswd .

      Thus, I added new condition, "symlink.target".

        allow_symlink /var/www/html/\*.html if symlink.target="\*.html"

        allow_symlink /var/www/html/\*\-.\* if symlink.target="\*\-.\*"

    @ Don't return -EAGAIN at ccs_socket_recvmsg_permission().

      It turned out that it is not permitted for accept() and recvmsg() to
      return -EAGAIN if poll() said connections/datagrams are ready. However,
      recvmsg() may return -EAGAIN and potentially confuse some applications
      because ccs_socket_recvmsg_permission() is returning -EAGAIN.

      Thus, I modified ccs_socket_recvmsg_permission() to return -ENOMEM
      rather than -EAGAIN.

Fix 2009/05/19

    @ Don't call get_fs_type() with a mutex held.

      Until now, when ccs_update_mount_acl() is called with unsupported
      filesystem, /sbin/modprobe is executed from get_fs_type() to load
      filesystem module. And get_fs_type() does not return until /sbin/modprobe
      finishes.

      This means that it will cause deadlock if /sbin/modprobe (which is
      executed via get_fs_type() in ccs_update_mount_acl()) calls
      ccs_update_mount_acl(); although it won't happen unless an administrator
      inserts execute_handler to call mount() requests in learning mode or to
      add "allow_mount" entries to /proc/ccs/system_policy .

      I modified to unlock the mutex before calling get_fs_type().

Fix 2009/05/20

    @ Update recvmsg() hooks.

      Since 1.5.0, I was doing network access control for incoming UDP and RAW
      packets inside skb_recv_datagram(). But to synchronize with LSM version,
      I moved ccs_recv_datagram_permission() hook from skb_recv_datagram() to
      udp_recvmsg()/udpv6_recvmsg()/raw_recvmsg()/rawv6_recvmsg() with name
      change to ccs_recvmsg_permission().

Version 1.6.8 2009/05/28   Feature enhancement release.

Fix 2009/07/03

    @ Fix buffer overrun when used with CONFIG_SLOB=y .

      Since 1.6.7 , ccs_allocate_execve_entry() was requesting for only 4000
      bytes while the comment says it is 4096 bytes. This may lead to buffer
      overrun when slob allocator is used, for slob allocator allocates exactly
      4000 bytes whereas slab and slub allocators allocate 4096 bytes.

Fix 2009/09/01

    @ Add garbage collector support.

      Until now, it was impossible to release memory used by deleted policy.
      I added SRCU based garbage collector so that memory used by deleted
      policy will be automatically released.

    @ Remove word length limitation and line length limitation.

      Until now, the max length of a word is 4000 and the max length of a line
      is 8192. To be able to handle longer pathnames, I removed these
      limitations. Now, the max length (except the domainname and
      argv[]/envp[]) is 128K (which is the max amount of memory kmalloc()
      can allocate in most environments).

    @ Support more fine grained profile configuration.

      Profile was reconstructed.

    @ Support more fine grained parameters restrictions.

      "allow_create", "allow_mkdir", "allow_mkfifo", "allow_mksock" check
      create mode. "allow_mkblock" and "allow_mkchar" check create mode and
      major/minor device numbers. "allow_chmod" check new mode. "allow_chown"
      checks new owner. "allow_chgrp" checks new group.

    @ Allow number grouping.

      To help specifying numeric values, a new directive "number_group" is
      introduced.

    @ Remove "alias" directive and "allow_argv0" directive.

      Until now, "allow_execute" used dereferenced pathname if it is a symlink
      unless explicitly specified by "alias" directive.

      Now, "allow_execute" uses symlink's pathname if it is a symlink.
      "exec.realpath" in "if" clause checks the dereferenced pathname.
      "exec.argv[0]" in "if" clause checks the invocation name.

    @ Remove /proc/ccs/system_policy and /etc/ccs/system_policy.conf .

      "deny_autobind" was moved to /proc/ccs/exception_policy and
      /etc/ccs/exception_policy.conf . Other directives were moved to
      /proc/ccs/domain_policy and /etc/ccs/domain_policy.conf .

    @ Remove syaoran filesystem.

      Since "allow_create"/"allow_mkdir"/"allow_mkfifo"/"allow_mksock"/
      "allow_mkblock"/"allow_mkchar"/"allow_chmod"/"allow_chown"/"allow_chgrp"
      can restrict mode changes and owner/group changes, there is no need to
      restrict these changes at filesystem level.

      Thus, I removed syaoran filesystem.

    @ Reduce spinlocks.

      Until now, TOMOYO was using own list for detecting memory leak. But as
      kernel 2.6.31 introduced memory leak detection mechanism
      ( CONFIG_DEBUG_KMEMLEAK ), TOMOYO no longer needs to use own list.

      I removed the list to reduce use of spinlocks.

    @ Rewrite ccs-patch-2.\*.diff .

      ccs-patch-2.\*.diff was rewritten like LSM hooks.

    @ Don't check "allow_read/write" for open-for-ioctl-only.

      open(pathname, 3) means open for ioctl() only.
      Until now, TOMOYO was checking "allow_read/write" for open(pathname, 3).
      But since TOMOYO checks "allow_ioctl" for ioctl(), I modified not to
      require "allow_read/write" for open(pathname, 3).

    @ Add missing sigqueue() and tgsigqueue() hooks.

      Until now, kill(), tkill(), tgkill() had hooks but sigqueue() and
      tgsigqueue() didn't.

    @ Move files from fs/ to security/ccsecurity.

      Config menu section changed from "File systems" to "Security options".

      Kernel config symbols changed from CONFIG_SAKURA CONFIG_TOMOYO
      CONFIG_SYAORAN to CONFIG_CCSECURITY .

    @ Add global PID to audit logs.

      ccs-queryd was using domainname for reaching the domain which the process
      belongs to, but the domain could be deleted while ccs-queryd is handling
      policy violation. If the domain is deleted, ccs-queryd no longer can
      reach the domain by domainname. Thus, ccs-queryd now uses PID for
      reaching the domain which the process belongs to.

      Kernel 2.6.24 introduced PID namespace. The PID in access logs generated
      by a process inside a container is useless for ccs-queryd for reaching
      the domain which the process belongs to.

      Thus, I added global PID in audit logs.

    @ Transit to new domain before do_execve() succeeds.

      Permission checks for interpreters and environment variables are
      done using new domain. In order to allow ccs-queryd to reach the new
      domain via global PID, I reverted "Don't transit to new domain until
      do_execve() succeeds." made on 2008/10/07.

Version 1.7.0 2009/09/03   Feature enhancement release.

Fix 2009/09/04

    @ Fix wrong ccs_profile() calls.

      I can't call ccs_profile() for profile existence test because
      ccs_profile() never returns NULL.

Fix 2009/09/06

    @ Fix wrong error code in ccs_try_alt_exec().

      ccs_try_alt_exec() was returning ENOMEM when kmalloc() failed.
      It needs to return -ENOMEM to fail.

Fix 2009/09/10

    @ Do not check umount() permission for mount(MS_MOVE) requests.

      Until 1.6.x , umount() restriction was black listing. In 1.7.0 , it is
      white listing. This change caused "mount --move old new" requests to
      require "allow_unmount old" permission in addition to
      "allow_mount old new --move 0" permission.
      But we don't want to allow umount(old) requests when we want to allow
      only mount(old, new, MS_MOVE) requests. Thus, I modified not to check
      "allow_unmount old" permission for mount(old, new, MS_MOVE) requests.

Fix 2009/09/11

    @ Support recursive match operators.

      Until now, ccs_path_matches_pattern() did not support recursive
      comparison. Thus, users had to repeat "/\*" when they want to specify
      recursively.

      I introduced "\{" and "\}" as repetition operator.
      To ensure consistency with TOMOYO's '/'-tokenized pattern matching rules
      and "\-" operator, only "/\{dir\}/" sequences (where dir does not contain
      '/') is permitted.

Fix 2009/09/24

    @ Don't check chmod/chown capability for requests from kernel.

      Until now, ccs_setattr_permission() was inserted in notify_change().
      But notify_change() is also called by requests from kernel (e.g. UnionFS)
      and it made difficult to use TOMOYO on UnionFS.

      Thus, I moved ccs_capable() checks from ccs_setattr_permission() to
      ccs_chmod_permission() and ccs_chown_permission(), and removed
      ccs_setattr_permission().

Fix 2009/09/25

    @ Embed more information into audit logs.

      Until now, /proc/ccs/grant_log /proc/ccs/reject_log /proc/ccs/query were
      not printing file's information (e.g. file's uid/gid/mode).

      Recently, users who started using "if" clause expect that the learning
      mode automatically adds various conditions like "if task.uid=path1.uid".

      But the profile will become too complicated if I support all possible
      conditions. Thus, I added all information which is enough to generate
      "if" clause with all possible conditions from audit logs.

      Now, the learning mode got different usage. Users can specify
      "CONFIG::learning={ max_entry=0 }" in the profile. All requests which
      are not permitted by policy will be sent to /proc/ccs/reject_log with
      "mode=learning" header lines. Users can selectively append conditions
      and append to the policy using "/usr/sbin/ccs-loadpolicy -d".
      The learning mode with "CONFIG::learning={ max_entry=0 }" is almost
      the same with the permissive mode, only difference is "mode=learning"
      and "mode=permissive".

Fix 2009/10/05

    @ Fix size truncation bug at ccs_memcmp().

      ccs_memcmp() was using "u8" for size parameter by error. Therefore, when
      size >= 256 was passed to ccs_memcmp(), it was doing partial comparison
      (incorrect result) or read overrun (CPU stall).

      ccs_memcmp() should use "size_t" for size parameter because size of
      "struct ccs_condition" may exceed 256 bytes if complicated condition was
      given.

Fix 2009/10/08

    @ Add CONFIG_CCSECURITY_DEFAULT_LOADER option.

      I made the default policy loader's pathname ( /sbin/ccs-init )
      configurable.

    @ Add CONFIG_CCSECURITY_ALTERNATIVE_TRIGGER option.

      Some environments do not have /sbin/init . In such environments, we need
      to use different program's pathname (e.g. /init or /linuxrc ) as
      activation trigger.

      Thus, I made the alternative trigger ( /sbin/ccs-start ) configurable.

Fix 2009/11/02

    @ Fix buffer contention.

      A permission like

        allow_env PATH if exec.envp["PATH"]="/"

      was not working since I was using the same buffer for both environment
      variable's name and value.

Fix 2009/11/03

    @ Fix memory leak in ccs_write_address_group_policy().

      I forgot to call kfree() if same entry was added.

    @ Reduce mutexes.

      I was using mutex_lock()/mutex_unlock() so that I can use
      atomic_dec_and_test() for removing an element from a list.
      I moved that operation to garbage collector in order to reduce frequency
      of mutex_lock()/mutex_unlock() calls.

    @ Escape from nested loops correctly.

      In ccs_read_address_group_policy(), I was escaping from nested loops
      correctly. But in ccs_read_path_group_policy() and
      ccs_read_number_group_policy(), I wasn't.

      As a result, reading path_group and number_group caused kernel oops
      when they were not read atomically.

Fix 2009/11/06

    @ Fix incorrect allow_mount audit log.

      Audit log for allow_mount was using decimal format.
      It needs to use hexadecimal format.

Fix 2009/11/09

    @ Add profile version check.

      To avoid upgrading from TOMOYO 1.6.x to TOMOYO 1.7.x without upgrading
      /proc/ccs/profile (which results in not protecting the system at all),
      I added a check for PROFILE_VERSION= .

Version 1.7.1 2009/11/11   Fourth anniversary release.

Fix 2009/11/13

    @ Don't use core_initcall() for initializing lock for GC.

     Some kernels call TOMOYO's hooks before processing core_initcall().
     Thus, I can't use core_initcall() for initializing lock for GC.

Fix 2009/11/18

    @ Don't check "allow_write" permission for open(O_RDONLY | O_TRUNC).

      Since TOMOYO checks "allow_truncate" permission rather than "allow_write"
      permission for O_TRUNC, I need to distinguish open(O_RDONLY | O_TRUNC)
      and open(O_RDWR | O_TRUNC). But I made a mistake between TOMOYO 1.7.0 and
      1.7.1 which made it impossible for TOMOYO for kernels 2.6.14 and earlier
      to distinguish them.

Fix 2009/11/27

    @ Use newly created domain's name for domain creation audit log.

      Since 1.7.0 , /proc/ccs/reject_log was by error using existing domain's
      name when auditing newly created domain's "use_profile" line.

Fix 2009/12/12

    @ Use rcu_read_lock() for find_task_by_pid().

      Since kernel 2.6.18 , caller of find_task_by_pid() needs to call
      rcu_read_lock() rather than read_lock(&tasklist_lock) because find_pid()
      uses RCU primitives but spinlock does not prevent RCU callback if
      preemptive RCU ( CONFIG_PREEMPT_RCU or CONFIG_TREE_PREEMPT_RCU ) is
      enabled.

Fix 2009/12/15

    @ Allow deleting "quota_exceeded" and "transition_failed" entries.

      To notify users of "this domain has too many entries to hold" and "some
      process in this domain was not able to perform domain transition",
      "quota_exceeded" and "transition_failed" messages are used respectively.
      These messages were not deletable. But it is more convenient for users
      to be notified again if such events occurred again after tuning policy.
      Thus, I made these messages deletable.

Fix 2009/12/17

    @ Don't check read permission in ccs_try_alt_exec().

      While I was trying to remove ccs_execve_list list for GC optimization
      between TOMOYO 1.7.0 and 1.7.1 , I made a mistake which made TOMOYO to
      check allow_read permission of the programs specified by execute_handler
      and denied_execute_handler keywords.

    @ Don't check DAC permission if disabled mode.

      I was checking DAC permissions regarding directory entry modification
      operations (e.g. mkdir()) even if mode=disabled . It is a waste of CPU
      resource to check DAC permissions when MAC permissions are not checked.
      Thus, I modified to skip DAC permission checks if mode=disabled .

Fix 2009/12/19

    @ Fix memory leak in ccs_environ().

      When I fixed a bug that a permission like

        allow_env PATH if exec.envp["PATH"]="/"

      was not working (2009/11/02), I allocated two buffers but only one buffer
      was released.

      This bug will trigger OOM killer if environment variable checking is
      enabled.

Fix 2010/01/17

    @ Use current domain's name for execute_handler audit log.

      Since 1.6.7 , /proc/ccs/grant_log was by error using next domain's name
      when auditing current domain's "execute_handler" line.

Fix 2010/03/02

    @ Allow domain transition without execve().

      To be able to split permissions for Apache's CGI programs which are
      executed without execve(), I added special domain transition which is
      performed by atomically writing '\0'-terminated binary string to
      /proc/ccs/.transition interface. For example, a process which belongs to
      "<kernel> /usr/sbin/httpd" domain will transit to
      "<kernel> /usr/sbin/httpd //app=cgi1\040id=10000" domain by atomically
      writing "app=cgi1 id=10000" + '\0' to /proc/ccs/.transition using
      Apache's ap_hook_handler() functionality.

      Note that '\0'-terminated binary string is converted to TOMOYO's string
      inside kernel and prefix "//" is automatically added to the string so
      that domainname does not conflict with domainnames created by execve().
      Without this prefix, if "<kernel> /usr/sbin/sshd /bin/bash" domain is
      allowed to open /proc/ccs/.transition for writing and
      "<kernel> /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain is allowed to
      access /etc/shadow , /bin/bash will be able to access /etc/shadow by
      atomically writing "/usr/bin/passwd" + '\0' to /proc/ccs/.transition .
      Allowing /bin/bash to access /etc/shadow is not what people want.

      Permission for this operation is checked by "allow_transit" keyword.
      Unlike "allow_execute" keyword, the string parameter for "allow_transit"
      keyword does not refer a real file on filesystem's namespace. Therefore,
      you can store any combination of parameters like LDAP's DN entry in the
      string parameter for "allow_transit" keyword.

Fix 2010/03/08

    @ Allow building as loadable kernel module.

      To be able to minimize filesize increment of vmlinux, I made it
      possible to compile TOMOYO Linux as loadable kernel module.
      Although patching the kernel source and recompiling the kernel are
      inevitable, this change will make it easier to enable TOMOYO Linux
      when there is a filesize limitation on vmlinux (e.g. embedded systems).

Fix 2010/03/25

    @ Fix ccs_get_ipv6_address() bug.

      Since 1.7.0 , ccs_get_ipv6_address() was by error returning address of
      "struct list_head ccs_address_list" if memory allocation failed.
      As a result, ccs_put_ipv6_address() will modify memory near
      "struct list_head ccs_address_list" if memory allocation failed.

Fix 2010/03/26

    @ Fix ccs_lport_reserved() bug.

      Since 1.7.0 , ccs_lport_reserved() was by error checking wrong port
      number. As a result, "deny_autobind" keyword was not working as expected.

Version 1.7.2 2010/04/01   Feature enhancement release.

Fix 2010/04/10

    @ Fix invalid "struct nameidata" to "struct path" conversion macro.

      Regarding kernels 2.6.24 and earlier, I was converting "struct nameidata"
      to "struct path" in caller side so that I can unify the callee function's
      parameter type. But it turned out that the macro I used did not follow C
      standards and did not work with gcc 4.x . As a result, "allow_pivot_root"
      keyword was not working as expected.

Fix 2010/05/05

    @ Fix incorrect audit on/off control.

      The grant_log= and reject_log= parameters of CONFIG::misc::env were not
      used because I forgot to update request type. As a result, those of
      CONFIG::file::execute were used for CONFIG::misc::env .

      Those of CONFIG::file::rewrite were not used because I forgot to update
      request type. As a result, those of CONFIG::file::truncate were used for
      CONFIG::file::rewrite .

Fix 2010/05/10

    @ Fix incorrect out of memory warning.

      Out of memory warnings were not printed in some cases by error.

Fix 2010/05/27

    @ Add missing rcu_dereference() for ccs_find_execute_handler().

      Since 1.7.0 , ccs_find_execute_handler() was by error using
      list_for_each_entry() rather than list_for_each_entry_rcu().
      This bug affects only Alpha architecture.

Fix 2010/06/03

    @ Fix missing sanity check for "file_pattern".

      Since 1.7.0 , ccs_write_pattern_policy() was by error accepting
      invalid pathname.

Fix 2010/06/09

    @ Add missing ccs_put_name() in ccs_parse_envp().

      Since 1.7.0 , ccs_parse_envp() was not calling ccs_put_name() if
      environment variable's value ('if exec.envp["name"]="value"' condition)
      was invalid.

    @ Add missing NULL check in ccs_condition().

      Since 1.7.0 , if 'if symlink.target=' part was given against non-file
      permissions (e.g. allow_env PATH if symlink.target="/"), it triggered
      NULL pointer dereference.

Fix 2010/10/28

    @ Fix umount() pathname calculation.

      "mount --bind /path/to/file1 /path/to/file2" is legal.
      Therefore, "umount /path/to/file2" is also legal.
      Do not automatically append trailing '/' if pathname to be unmounted
      does not end with '/'.

    @ Add preserve KABI compatibility option. (2.6 kernels only)

      TOMOYO needs "struct ccs_domain_info *" and "u32" for each
      "struct task_struct". But embedding these variables into
      "struct task_struct" breaks KABI for prebuilt kernel modules (which
      means that you will need to rebuild prebuilt kernel modules).

      Since KABI is commonly used (compared to 5 years ago), asking users to
      rebuild kernel modules which are not included in kernel package is no
      longer preferable. Therefore, I added a new option that keeps
      "struct task_struct" unmodified in order to keep KABI.

      Note that you have to use ccs-patch-2.6.\*.diff which patches
      kernel/fork.c in order to use this option. Otherwise, TOMOYO will leak
      memory whenever "struct task_struct" is released.

    @ Change directives.

      I removed "allow_" prefix from directives. New directives for files are
      prefixed with "file ". For example, "allow_read" changed to "file read",
      "allow_ioctl" changed to "file ioctl". New directive for "allow_network
      TCP" is "network inet stream", "allow_network UDP" is "network inet
      dgram", "allow_network RAW" is "network inet raw". New directive for
      "allow_env" is "misc env". New directive for "allow_signal" is "ipc
      signal". New directive for "allow_capability" is "capability". These new
      directives correspond with keywords used by profile's CONFIG lines.

      I removed "deny_rewrite" and "allow_rewrite" directives and introduced
      "file append" directive. Thus, permission for open(O_WRONLY | O_APPEND)
      changed from "allow_write" + "allow_rewrite" to "file append".

      I removed "SYS_MOUNT", "SYS_UMOUNT", "SYS_CHROOT", "SYS_KILL",
      "SYS_LINK", "SYS_SYMLINK", "SYS_RENAME", "SYS_UNLINK", "SYS_CHMOD",
      "SYS_CHOWN", "SYS_IOCTL", "SYS_PIVOT_ROOT" keywords from capabilities
      because these permissions can be checked by other directives (e.g.
      "file mount", "ipc signal").

      I also removed "conceal_mount" keyword from capabilities because this
      check requires hooks in filesystem part while almost all hooks for
      filesystem part have moved to LSM by Linux 2.6.34.

      New directive for "execute_handler" is "task auto_execute_handler",
      "denied_execute_handler" is "task denied_execute_handler".

    @ Distinguish send() and recv() operations.

      Until now, it was impossible for UDP and IP sockets to allow either
      only sending or only receiving because permissions were aggregated with
      "connect" keyword. I broke "connect" keyword into "send" and "recv"
      keywords so that you can keep access control for send() operation enabled
      when you have to disable access control for recv() operation due to
      application breakage by discarding incoming datagram.

    @ Add Unix domain socket restriction support.

      Until now, it was possible to restrict only inet domain sockets (i.e.
      TCP/UDP/RAW). I added restriction for Unix domain sockets (i.e. stream/
      dgram/seqpacket). New directive "network unix" is added as well as
      "network inet" directive.

    @ Allow specifying multiple permissions in a line.

      Until now, only "allow_read/write" can be specified for combination of
      "allow_read" + "allow_write". Now, you can combine other permissions as
      long as type of parameters for these permissions is same. For example,
      "file read/write/append/execute/unlink/truncate /tmp/file" is correct
      but "file read/write/create /tmp/file" is wrong because "file create"
      requires create mode whereas "file read" and "file write" do not.

    @ Allow wildcard for execute permission and domainname.

      Until now, to execute programs with temporary names, "aggregator" is
      needed. To simplify code, I modified to accept wildcards for execute
      permission and domainname. Now, you can directly specify
      "file execute /tmp/logrotate.\?\?\?\?\?\?" and use
      "/tmp/logrotate.\?\?\?\?\?\?" within domainnames.

    @ Change pathname for non-rename()able filesystems.

      LSM version of TOMOYO wants to use /proc/self/ rather than /proc/$PID/ if
      $PID matches current thread's process ID in order to prevent current
      thread from accessing other process's information unless needed.
      But since procfs can be mounted on various locations (e.g. /proc/ /proc2/
      /p/ /tmp/foo/100/p/ ), LSM version of TOMOYO cannot tell that whether the
      numeric part in the string returned by __d_path() represents process ID
      or not.

      Therefore, to be able to convert from $PID to self no matter where procfs
      is mounted, I changed pathname representations for filesystems which do
      not support rename() operation (e.g. proc, sysfs, securityfs).

      Now, "/proc/self/mounts" changed to "proc:/self/mounts" and
      "/sys/kernel/security/" changed to "sys:/kernel/security/" and
      "/dev/pts/0" changed to "devpts:/0".

    @ Add a new keyword "any" for domain transition control.

      To be able to make it easier to apply auto_execute_handler on each
      domain, I added "any" keyword to domain transition control keywords. Now,
      "initialize_domain /usr/sbin/sshd" changed to
      "initialize_domain /usr/sbin/sshd from any" and
      "keep_domain <kernel> /usr/sbin/sshd /bin/bash" changed to
      "keep_domain any from <kernel> /usr/sbin/sshd /bin/bash".

      "keep_domain /path/to/auto_execute_handler from any" will allow you to
      apply auto_execute_handler for any domains without creating domains for
      auto_execute_handler.

    @ Change buffering mode for reading policy.

      To be able to read() very very long lines correctly, I changed the way
      TOMOYO buffers policy for reading.

    @ Introduce "acl_group" keyword.

      Until now, it was possible to specify only "allow_read" and "allow_env"
      keywords in the exception policy.

      Since some operations like "file read/write/append /dev/null" and
      "network UDP send/recv @DNS_SERVER 53" are very common and should be
      permitted to all domains, I introduced "acl_group" keyword for giving
      such permissions.

      For example, specify "acl_group 0 file read/write/append /dev/null" in
      the exception policy and specify "use_group 0" from the domains in the
      domain policy.

      "ignore_global_allow_read" and "ignore_global_allow_env" directives were
      removed from domain policy and "use_group" keyword was added.

    @ Remove "if" and "; set" keyword.

      I removed need for specifying these keyword.
      You can simply specify like below.

        file read /etc/shadow task.uid=0

    @ Remove "file_pattern" keyword.

      I removed "file_pattern" keyword because it is impossible to predefine
      all possible pathname patterns. Also, learning pathnames using incomplete
      patterns makes it difficult to later replace using "path_group" keyword.

    @ Replace verbose= parameter with statistic interface.

      Since it is noisy if a lot of policy violation messages are printed,
      I removed printk(). To be able to check whether policy violation occurred
      or not, I introduced /proc/ccs/stat interface which counts number of
      policy violations occurred. You can firstly check /proc/ccs/stat and then
      check /proc/ccs/reject_log .

    @ Remove global preference.

      I removed global preference in order to make code simpler.

    @ Allow controlling generation of access granted logs for per an entry
      basis.

      I added per-entry flag which controls generation of grant logs because
      Xen and KVM issues ioctl requests so frequently. For example,

        file ioctl /dev/null 0x5401 grant_log=no

      will suppress /proc/ccs/grant_log even if preference says grant_log=yes .

        file ioctl /dev/null 0x5401 grant_log=yes

      will generate /proc/ccs/grant_log even if preference says grant_log=no .

        file ioctl /dev/null 0x5401

      will generate /proc/ccs/grant_log only if preference says grant_log=yes .

      This flag is intended for frequently accessed resources like

        file read /var/www/html/\{\*\}/\*.html grant_log=no

      .

    @ Automatically create domain by execve() even if enforcing mode.

      Until now, new domains are not created if the domain was not defined and
      current domain is enforcing mode ("CONFIG::file::execute=enforcing").

      To be able to restrict shell session without using "keep_domain",
      I changed to create new domains automatically even if current domain is
      enforcing mode.

    @ Replace "task.state" with "auto_domain_transition".

      task.state is difficult to use. Thus, I replaced task.state with
      auto_domain_transition which performs domain transition instead of
      changing current process's state variables.

      If domain transition failed, current process will be killed by SIGKILL
      signal. This should not happen in normal circumstances, for you know the
      domain to transit to and thereby you will define the domain beforehand
      when you use "auto_domain_transition" keyword.

    @ Replace "allow_transit" with "task manual_domain_transition".

      I changed this directive to specify absolute domainname (e.g.
      "<kernel> /usr/sbin/httpd //app=cgi1\040id=10000") rather than virtual
      pathname (e.g. "//app=cgi1\040id=10000") because you know the domain to
      transit to and thereby you will define the domain beforehand when you use
      "task manual_domain_transition" directive.

      This change allows you to jump to arbitrary domain.

      Note that this change also reverts "Change /proc/ccs/info/self_domain ."
      made on 2006/10/24. Now, 'cat < /proc/ccs/info/self_domain' will act like
      'cat /proc/ccs/info/self_domain'. Programs depending on old assumption
      need to be updated.

    @ Add "task auto_domain_transition".

      This is similar to "task manual_domain_transition", but is automatically
      applied whenever conditions are met. For example,

        task auto_domain_transition <kernel> //./non-root task.uid!=0

      will automatically jump to "<kernel> //./non-root" domain if current
      process's UID is not 0 whereas

        task manual_domain_transition <kernel> //./non-root task.uid!=0

      will jump to "<kernel> //./non-root" domain if current process's UID is
      not 0 and current process wrote "<kernel> //./non-root" to
      /proc/ccs/self_domain interface.

      If domain transition failed, current process will be killed by SIGKILL
      signal.

    @ Optimize for object's size.

      I merged similar code in order to reduce object's filesize.

Version 1.8.0 2010/11/11   Fifth anniversary release.

Fix 2010/12/01

    @ Use same interface for audit logs.

      To be able to perform fine grained filtering by /usr/sbin/ccs-auditd ,
      I merged /proc/ccs/grant_log and /proc/ccs/reject_log as
      /proc/ccs/audit and added granted=yes or granted=no to audit logs.

Fix 2010/12/17

    @ Split ccs_null_security into ccs_default_security and ccs_oom_security.

      ccs_null_security is used by preserve KABI compatibility option and is
      used for providing default values against threads which have not yet
      allocated memory for their security contexts.

      If current thread failed to allocate memory for current thread's security
      context, current thread uses ccs_null_security. Since current thread is
      allowed to modify current thread's security context, current thread might
      modify ccs_null_security which should not be modified for any reason.

      Therefore, I split ccs_null_security into ccs_default_security and
      ccs_oom_security and use ccs_oom_security when current thread failed to
      allocate memory for current thread's security context.

      Threads which do not share ccs_oom_security are not affected by threads
      which share ccs_oom_security. Threads which share ccs_oom_security will
      experience temporary inconsistency, but such threads are about to be
      killed by SIGKILL signal.

Fix 2011/01/11

    @ Use filesystem name for unnamed devices when vfsmount is missing.

      "Change pathname for non-rename()able filesystems." changed to use
      "$fsname:" if the filesystem does not support rename() operation and
      "dev($major,$minor):" otherwise when vfsmount is missing. But it turned
      out that it is useless to use "dev($major,$minor):" for unnamed devices
      (filesystems with $major == 0). Thus, I changed to use "$fsname:" rather
      than "dev($major,$minor):" for filesystems with $major == 0 when vfsmount
      is missing.

Fix 2011/02/07

    @ Fix infinite loop bug when reading /proc/ccs/audit or /proc/ccs/query .

      In ccs_flush(), head->r.w[0] holds pointer to string data to be printed.
      But head->r.w[0] was updated only when the string data was partially
      printed (because head->r.w[0] will be updated by head->r.w[1] later if
      completely printed). However, regarding /proc/ccs/audit and
      /proc/ccs/query , an additional '\0' is printed after the string data was
      completely printed. But if free space for read buffer became 0 before
      printing the additional '\0', ccs_flush() was returning without updating
      head->r.w[0]. As a result, ccs_flush() forever reprints already printed
      string data.

Fix 2011/03/01

    @ Run garbage collector without waiting for /proc/ccs/ users.

      Currently TOMOYO holds SRCU lock upon open() and releases it upon close()
      because list elements stored in the "struct ccs_io_buffer" instances are
      accessed until close() is called. However, such SRCU usage causes lockdep
      to complain about leaving the kernel with SRCU lock held. Therefore,
      I changed to hold/release SRCU upon each read()/write() by selectively
      deferring kfree() by keeping track of the "struct ccs_io_buffer"
      instances.

Fix 2011/03/05

    @ Support built-in policy configuration.

      To be able to start using enforcing mode from the early stage of boot
      sequence, I added support for built-in policy configuration and
      activating access control without calling external policy loader program.

      This will be useful for systems where operations which can lead to the
      hijacking of the boot sequence are needed before loading the policy.
      For example, you can activate immediately after loading the fixed part of
      policy which will allow only operations needed for mounting a partition
      which contains the variant part of policy and verifying (e.g. running GPG
      check) and loading the variant part of policy. Since you can start using
      enforcing mode from the beginning, you can reduce the possibility of
      hijacking the boot sequence.

Fix 2011/03/10

    @ Remove /proc/ccs/meminfo interface.

      Please use /proc/ccs/stat interface instead.

Fix 2011/03/15

    @ Pack policy when printing via /proc/ccs/ interface.

      The kernel side is ready for accepting packed input like

        file read/write/execute /path/to/file

      but was using unpacked output like

        file read /path/to/file
        file write /path/to/file
        file execute /path/to/file

      because most of userland tools were not ready for accepting packed input.

      The advantages of using packed policy are that it makes policy files
      smaller and it speeds up loading/saving policy files.

      Since most of userland tools are ready for accepting packed input by now,
      I changed to use packed policy for both input and output.

Fix 2011/03/31

    @ Fix conditional policy parsing.

      Since exec.realpath= and symlink.target= accept path_group,
      symlink.target="@foo" was by error parsed as symlink.target=@foo .

    @ Serialize updating profile's comment line.

      We need to serialize when updating COMMENT= line in /proc/ccs/profile .

Version 1.8.1   2011/04/01   Usability enhancement with "Zettai, Daijoubudayo" release!
