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_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_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" keyword.
To be able to fully utilize "alt_exec" feature,
I added "force_alt_exec" keyword so that
all execute requests are replaced by the execute request of a program
specified by alt_exec feature.
If this keyword 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" keyword 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" keyword takes one pathname which is
invoked whenever execve() request is issued. Thus, any "allow_execute"
keywords in a domain with "execute_handler" are ignored.
This keyword 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" keyword to "denied_execute_handler".
The "denied_execute_handler" keyword 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" keywords in the domain matched.
(2) The execve() request was rejected in enforcing mode.
(3) "execute_handler" keyword is not used by the domain.
This keyword 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" keywords
if the current process is executing programs specified by
"execute_handler" or "denied_execute_handler" keyword.
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.