File operation restriction part.
This file controls file related operations of TOMOYO Linux.
tomoyo/tomoyo.c calls the following six functions in this file.
Each function handles the following access types.
* tomoyo_check_file_perm
sysctl()'s "read" and "write".
* tomoyo_check_exec_perm
"execute".
* tomoyo_check_open_permission
open(2) for "read" and "write".
* tomoyo_check_1path_perm
"create", "unlink", "mkdir", "rmdir", "mkfifo",
"mksock", "mkblock", "mkchar", "truncate" and "symlink".
* tomoyo_check_2path_perm
"rename" and "unlink".
* tomoyo_check_rewrite_permission
"rewrite".
("rewrite" are operations which may lose already recorded data of a file,
i.e. open(!O_APPEND) || open(O_TRUNC) || truncate() || ftruncate())
The functions which actually checks ACLs are the following three functions.
Each function handles the following access types.
ACL directive is expressed by "allow_<access type>".
* tomoyo_check_file_acl
Open() operation and execve() operation.
("read", "write", "read/write" and "execute")
* tomoyo_check_single_write_acl
Directory modification operations with 1 pathname.
("create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock",
"mkblock", "mkchar", "truncate", "symlink" and "rewrite")
* tomoyo_check_double_write_acl
Directory modification operations with 2 pathname.
("link" and "rename")
Also, this file contains handlers of some utility directives
for file related operations.
* "allow_read": specifies globally (for all domains) readable files.
* "path_group": specifies pathname macro.
* "deny_rewrite": restricts rewrite operation.
Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Toshiharu Harada <haradats@nttdata.co.jp>
Signed-off-by: James Morris <jmorris@namei.org>
2009-02-05 17:18:14 +09:00
/*
* security / tomoyo / file . c
*
* Implementation of the Domain - Based Mandatory Access Control .
*
* Copyright ( C ) 2005 - 2009 NTT DATA CORPORATION
*
2009-04-08 22:31:28 +09:00
* Version : 2.2 .0 2009 / 04 / 01
File operation restriction part.
This file controls file related operations of TOMOYO Linux.
tomoyo/tomoyo.c calls the following six functions in this file.
Each function handles the following access types.
* tomoyo_check_file_perm
sysctl()'s "read" and "write".
* tomoyo_check_exec_perm
"execute".
* tomoyo_check_open_permission
open(2) for "read" and "write".
* tomoyo_check_1path_perm
"create", "unlink", "mkdir", "rmdir", "mkfifo",
"mksock", "mkblock", "mkchar", "truncate" and "symlink".
* tomoyo_check_2path_perm
"rename" and "unlink".
* tomoyo_check_rewrite_permission
"rewrite".
("rewrite" are operations which may lose already recorded data of a file,
i.e. open(!O_APPEND) || open(O_TRUNC) || truncate() || ftruncate())
The functions which actually checks ACLs are the following three functions.
Each function handles the following access types.
ACL directive is expressed by "allow_<access type>".
* tomoyo_check_file_acl
Open() operation and execve() operation.
("read", "write", "read/write" and "execute")
* tomoyo_check_single_write_acl
Directory modification operations with 1 pathname.
("create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock",
"mkblock", "mkchar", "truncate", "symlink" and "rewrite")
* tomoyo_check_double_write_acl
Directory modification operations with 2 pathname.
("link" and "rename")
Also, this file contains handlers of some utility directives
for file related operations.
* "allow_read": specifies globally (for all domains) readable files.
* "path_group": specifies pathname macro.
* "deny_rewrite": restricts rewrite operation.
Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Toshiharu Harada <haradats@nttdata.co.jp>
Signed-off-by: James Morris <jmorris@namei.org>
2009-02-05 17:18:14 +09:00
*
*/
# include "common.h"
# include "tomoyo.h"
# include "realpath.h"
# define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
2009-06-08 12:37:39 +09:00
/*
* tomoyo_globally_readable_file_entry is a structure which is used for holding
* " allow_read " entries .
* It has following fields .
*
* ( 1 ) " list " which is linked to tomoyo_globally_readable_list .
* ( 2 ) " filename " is a pathname which is allowed to open ( O_RDONLY ) .
* ( 3 ) " is_deleted " is a bool which is true if marked as deleted , false
* otherwise .
*/
File operation restriction part.
This file controls file related operations of TOMOYO Linux.
tomoyo/tomoyo.c calls the following six functions in this file.
Each function handles the following access types.
* tomoyo_check_file_perm
sysctl()'s "read" and "write".
* tomoyo_check_exec_perm
"execute".
* tomoyo_check_open_permission
open(2) for "read" and "write".
* tomoyo_check_1path_perm
"create", "unlink", "mkdir", "rmdir", "mkfifo",
"mksock", "mkblock", "mkchar", "truncate" and "symlink".
* tomoyo_check_2path_perm
"rename" and "unlink".
* tomoyo_check_rewrite_permission
"rewrite".
("rewrite" are operations which may lose already recorded data of a file,
i.e. open(!O_APPEND) || open(O_TRUNC) || truncate() || ftruncate())
The functions which actually checks ACLs are the following three functions.
Each function handles the following access types.
ACL directive is expressed by "allow_<access type>".
* tomoyo_check_file_acl
Open() operation and execve() operation.
("read", "write", "read/write" and "execute")
* tomoyo_check_single_write_acl
Directory modification operations with 1 pathname.
("create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock",
"mkblock", "mkchar", "truncate", "symlink" and "rewrite")
* tomoyo_check_double_write_acl
Directory modification operations with 2 pathname.
("link" and "rename")
Also, this file contains handlers of some utility directives
for file related operations.
* "allow_read": specifies globally (for all domains) readable files.
* "path_group": specifies pathname macro.
* "deny_rewrite": restricts rewrite operation.
Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Toshiharu Harada <haradats@nttdata.co.jp>
Signed-off-by: James Morris <jmorris@namei.org>
2009-02-05 17:18:14 +09:00
struct tomoyo_globally_readable_file_entry {
struct list_head list ;
const struct tomoyo_path_info * filename ;
bool is_deleted ;
} ;
2009-06-08 12:37:39 +09:00
/*
* tomoyo_pattern_entry is a structure which is used for holding
* " tomoyo_pattern_list " entries .
* It has following fields .
*
* ( 1 ) " list " which is linked to tomoyo_pattern_list .
* ( 2 ) " pattern " is a pathname pattern which is used for converting pathnames
* to pathname patterns during learning mode .
* ( 3 ) " is_deleted " is a bool which is true if marked as deleted , false
* otherwise .
*/
File operation restriction part.
This file controls file related operations of TOMOYO Linux.
tomoyo/tomoyo.c calls the following six functions in this file.
Each function handles the following access types.
* tomoyo_check_file_perm
sysctl()'s "read" and "write".
* tomoyo_check_exec_perm
"execute".
* tomoyo_check_open_permission
open(2) for "read" and "write".
* tomoyo_check_1path_perm
"create", "unlink", "mkdir", "rmdir", "mkfifo",
"mksock", "mkblock", "mkchar", "truncate" and "symlink".
* tomoyo_check_2path_perm
"rename" and "unlink".
* tomoyo_check_rewrite_permission
"rewrite".
("rewrite" are operations which may lose already recorded data of a file,
i.e. open(!O_APPEND) || open(O_TRUNC) || truncate() || ftruncate())
The functions which actually checks ACLs are the following three functions.
Each function handles the following access types.
ACL directive is expressed by "allow_<access type>".
* tomoyo_check_file_acl
Open() operation and execve() operation.
("read", "write", "read/write" and "execute")
* tomoyo_check_single_write_acl
Directory modification operations with 1 pathname.
("create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock",
"mkblock", "mkchar", "truncate", "symlink" and "rewrite")
* tomoyo_check_double_write_acl
Directory modification operations with 2 pathname.
("link" and "rename")
Also, this file contains handlers of some utility directives
for file related operations.
* "allow_read": specifies globally (for all domains) readable files.
* "path_group": specifies pathname macro.
* "deny_rewrite": restricts rewrite operation.
Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Toshiharu Harada <haradats@nttdata.co.jp>
Signed-off-by: James Morris <jmorris@namei.org>
2009-02-05 17:18:14 +09:00
struct tomoyo_pattern_entry {
struct list_head list ;
const struct tomoyo_path_info * pattern ;
bool is_deleted ;
} ;
2009-06-08 12:37:39 +09:00
/*
* tomoyo_no_rewrite_entry is a structure which is used for holding
* " deny_rewrite " entries .
* It has following fields .
*
* ( 1 ) " list " which is linked to tomoyo_no_rewrite_list .
* ( 2 ) " pattern " is a pathname which is by default not permitted to modify
* already existing content .
* ( 3 ) " is_deleted " is a bool which is true if marked as deleted , false
* otherwise .
*/
File operation restriction part.
This file controls file related operations of TOMOYO Linux.
tomoyo/tomoyo.c calls the following six functions in this file.
Each function handles the following access types.
* tomoyo_check_file_perm
sysctl()'s "read" and "write".
* tomoyo_check_exec_perm
"execute".
* tomoyo_check_open_permission
open(2) for "read" and "write".
* tomoyo_check_1path_perm
"create", "unlink", "mkdir", "rmdir", "mkfifo",
"mksock", "mkblock", "mkchar", "truncate" and "symlink".
* tomoyo_check_2path_perm
"rename" and "unlink".
* tomoyo_check_rewrite_permission
"rewrite".
("rewrite" are operations which may lose already recorded data of a file,
i.e. open(!O_APPEND) || open(O_TRUNC) || truncate() || ftruncate())
The functions which actually checks ACLs are the following three functions.
Each function handles the following access types.
ACL directive is expressed by "allow_<access type>".
* tomoyo_check_file_acl
Open() operation and execve() operation.
("read", "write", "read/write" and "execute")
* tomoyo_check_single_write_acl
Directory modification operations with 1 pathname.
("create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock",
"mkblock", "mkchar", "truncate", "symlink" and "rewrite")
* tomoyo_check_double_write_acl
Directory modification operations with 2 pathname.
("link" and "rename")
Also, this file contains handlers of some utility directives
for file related operations.
* "allow_read": specifies globally (for all domains) readable files.
* "path_group": specifies pathname macro.
* "deny_rewrite": restricts rewrite operation.
Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Toshiharu Harada <haradats@nttdata.co.jp>
Signed-off-by: James Morris <jmorris@namei.org>
2009-02-05 17:18:14 +09:00
struct tomoyo_no_rewrite_entry {
struct list_head list ;
const struct tomoyo_path_info * pattern ;
bool is_deleted ;
} ;
/* Keyword array for single path operations. */
static const char * tomoyo_sp_keyword [ TOMOYO_MAX_SINGLE_PATH_OPERATION ] = {
[ TOMOYO_TYPE_READ_WRITE_ACL ] = " read/write " ,
[ TOMOYO_TYPE_EXECUTE_ACL ] = " execute " ,
[ TOMOYO_TYPE_READ_ACL ] = " read " ,
[ TOMOYO_TYPE_WRITE_ACL ] = " write " ,
[ TOMOYO_TYPE_CREATE_ACL ] = " create " ,
[ TOMOYO_TYPE_UNLINK_ACL ] = " unlink " ,
[ TOMOYO_TYPE_MKDIR_ACL ] = " mkdir " ,
[ TOMOYO_TYPE_RMDIR_ACL ] = " rmdir " ,
[ TOMOYO_TYPE_MKFIFO_ACL ] = " mkfifo " ,
[ TOMOYO_TYPE_MKSOCK_ACL ] = " mksock " ,
[ TOMOYO_TYPE_MKBLOCK_ACL ] = " mkblock " ,
[ TOMOYO_TYPE_MKCHAR_ACL ] = " mkchar " ,
[ TOMOYO_TYPE_TRUNCATE_ACL ] = " truncate " ,
[ TOMOYO_TYPE_SYMLINK_ACL ] = " symlink " ,
[ TOMOYO_TYPE_REWRITE_ACL ] = " rewrite " ,
} ;
/* Keyword array for double path operations. */
static const char * tomoyo_dp_keyword [ TOMOYO_MAX_DOUBLE_PATH_OPERATION ] = {
[ TOMOYO_TYPE_LINK_ACL ] = " link " ,
[ TOMOYO_TYPE_RENAME_ACL ] = " rename " ,
} ;
/**
* tomoyo_sp2keyword - Get the name of single path operation .
*
* @ operation : Type of operation .
*
* Returns the name of single path operation .
*/
const char * tomoyo_sp2keyword ( const u8 operation )
{
return ( operation < TOMOYO_MAX_SINGLE_PATH_OPERATION )
? tomoyo_sp_keyword [ operation ] : NULL ;
}
/**
* tomoyo_dp2keyword - Get the name of double path operation .
*
* @ operation : Type of operation .
*
* Returns the name of double path operation .
*/
const char * tomoyo_dp2keyword ( const u8 operation )
{
return ( operation < TOMOYO_MAX_DOUBLE_PATH_OPERATION )
? tomoyo_dp_keyword [ operation ] : NULL ;
}
/**
* tomoyo_strendswith - Check whether the token ends with the given token .
*
* @ name : The token to check .
* @ tail : The token to find .
*
* Returns true if @ name ends with @ tail , false otherwise .
*/
static bool tomoyo_strendswith ( const char * name , const char * tail )
{
int len ;
if ( ! name | | ! tail )
return false ;
len = strlen ( name ) - strlen ( tail ) ;
return len > = 0 & & ! strcmp ( name + len , tail ) ;
}
/**
* tomoyo_get_path - Get realpath .
*
* @ path : Pointer to " struct path " .
*
* Returns pointer to " struct tomoyo_path_info " on success , NULL otherwise .
*/
static struct tomoyo_path_info * tomoyo_get_path ( struct path * path )
{
int error ;
struct tomoyo_path_info_with_data * buf = tomoyo_alloc ( sizeof ( * buf ) ) ;
if ( ! buf )
return NULL ;
/* Reserve one byte for appending "/". */
error = tomoyo_realpath_from_path2 ( path , buf - > body ,
sizeof ( buf - > body ) - 2 ) ;
if ( ! error ) {
buf - > head . name = buf - > body ;
tomoyo_fill_path_info ( & buf - > head ) ;
return & buf - > head ;
}
tomoyo_free ( buf ) ;
return NULL ;
}
/* Lock for domain->acl_info_list. */
DECLARE_RWSEM ( tomoyo_domain_acl_info_list_lock ) ;
static int tomoyo_update_double_path_acl ( const u8 type , const char * filename1 ,
const char * filename2 ,
struct tomoyo_domain_info *
const domain , const bool is_delete ) ;
static int tomoyo_update_single_path_acl ( const u8 type , const char * filename ,
struct tomoyo_domain_info *
const domain , const bool is_delete ) ;
2009-06-08 12:37:39 +09:00
/*
* tomoyo_globally_readable_list is used for holding list of pathnames which
* are by default allowed to be open ( ) ed for reading by any process .
*
* An entry is added by
*
* # echo ' allow_read / lib / libc - 2.5 . so ' > \
* / sys / kernel / security / tomoyo / exception_policy
*
* and is deleted by
*
* # echo ' delete allow_read / lib / libc - 2.5 . so ' > \
* / sys / kernel / security / tomoyo / exception_policy
*
* and all entries are retrieved by
*
* # grep ^ allow_read / sys / kernel / security / tomoyo / exception_policy
*
* In the example above , any process is allowed to
* open ( " /lib/libc-2.5.so " , O_RDONLY ) .
* One exception is , if the domain which current process belongs to is marked
* as " ignore_global_allow_read " , current process can ' t do so unless explicitly
* given " allow_read /lib/libc-2.5.so " to the domain which current process
* belongs to .
*/
File operation restriction part.
This file controls file related operations of TOMOYO Linux.
tomoyo/tomoyo.c calls the following six functions in this file.
Each function handles the following access types.
* tomoyo_check_file_perm
sysctl()'s "read" and "write".
* tomoyo_check_exec_perm
"execute".
* tomoyo_check_open_permission
open(2) for "read" and "write".
* tomoyo_check_1path_perm
"create", "unlink", "mkdir", "rmdir", "mkfifo",
"mksock", "mkblock", "mkchar", "truncate" and "symlink".
* tomoyo_check_2path_perm
"rename" and "unlink".
* tomoyo_check_rewrite_permission
"rewrite".
("rewrite" are operations which may lose already recorded data of a file,
i.e. open(!O_APPEND) || open(O_TRUNC) || truncate() || ftruncate())
The functions which actually checks ACLs are the following three functions.
Each function handles the following access types.
ACL directive is expressed by "allow_<access type>".
* tomoyo_check_file_acl
Open() operation and execve() operation.
("read", "write", "read/write" and "execute")
* tomoyo_check_single_write_acl
Directory modification operations with 1 pathname.
("create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock",
"mkblock", "mkchar", "truncate", "symlink" and "rewrite")
* tomoyo_check_double_write_acl
Directory modification operations with 2 pathname.
("link" and "rename")
Also, this file contains handlers of some utility directives
for file related operations.
* "allow_read": specifies globally (for all domains) readable files.
* "path_group": specifies pathname macro.
* "deny_rewrite": restricts rewrite operation.
Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Toshiharu Harada <haradats@nttdata.co.jp>
Signed-off-by: James Morris <jmorris@namei.org>
2009-02-05 17:18:14 +09:00
static LIST_HEAD ( tomoyo_globally_readable_list ) ;
static DECLARE_RWSEM ( tomoyo_globally_readable_list_lock ) ;
/**
* tomoyo_update_globally_readable_entry - Update " struct tomoyo_globally_readable_file_entry " list .
*
* @ filename : Filename unconditionally permitted to open ( ) for reading .
* @ is_delete : True if it is a delete request .
*
* Returns 0 on success , negative value otherwise .
*/
static int tomoyo_update_globally_readable_entry ( const char * filename ,
const bool is_delete )
{
struct tomoyo_globally_readable_file_entry * new_entry ;
struct tomoyo_globally_readable_file_entry * ptr ;
const struct tomoyo_path_info * saved_filename ;
int error = - ENOMEM ;
if ( ! tomoyo_is_correct_path ( filename , 1 , 0 , - 1 , __func__ ) )
return - EINVAL ;
saved_filename = tomoyo_save_name ( filename ) ;
if ( ! saved_filename )
return - ENOMEM ;
down_write ( & tomoyo_globally_readable_list_lock ) ;
list_for_each_entry ( ptr , & tomoyo_globally_readable_list , list ) {
if ( ptr - > filename ! = saved_filename )
continue ;
ptr - > is_deleted = is_delete ;
error = 0 ;
goto out ;
}
if ( is_delete ) {
error = - ENOENT ;
goto out ;
}
new_entry = tomoyo_alloc_element ( sizeof ( * new_entry ) ) ;
if ( ! new_entry )
goto out ;
new_entry - > filename = saved_filename ;
list_add_tail ( & new_entry - > list , & tomoyo_globally_readable_list ) ;
error = 0 ;
out :
up_write ( & tomoyo_globally_readable_list_lock ) ;
return error ;
}
/**
* tomoyo_is_globally_readable_file - Check if the file is unconditionnaly permitted to be open ( ) ed for reading .
*
* @ filename : The filename to check .
*
* Returns true if any domain can open @ filename for reading , false otherwise .
*/
static bool tomoyo_is_globally_readable_file ( const struct tomoyo_path_info *
filename )
{
struct tomoyo_globally_readable_file_entry * ptr ;
bool found = false ;
down_read ( & tomoyo_globally_readable_list_lock ) ;
list_for_each_entry ( ptr , & tomoyo_globally_readable_list , list ) {
if ( ! ptr - > is_deleted & &
tomoyo_path_matches_pattern ( filename , ptr - > filename ) ) {
found = true ;
break ;
}
}
up_read ( & tomoyo_globally_readable_list_lock ) ;
return found ;
}
/**
* tomoyo_write_globally_readable_policy - Write " struct tomoyo_globally_readable_file_entry " list .
*
* @ data : String to parse .
* @ is_delete : True if it is a delete request .
*
* Returns 0 on success , negative value otherwise .
*/
int tomoyo_write_globally_readable_policy ( char * data , const bool is_delete )
{
return tomoyo_update_globally_readable_entry ( data , is_delete ) ;
}
/**
* tomoyo_read_globally_readable_policy - Read " struct tomoyo_globally_readable_file_entry " list .
*
* @ head : Pointer to " struct tomoyo_io_buffer " .
*
* Returns true on success , false otherwise .
*/
bool tomoyo_read_globally_readable_policy ( struct tomoyo_io_buffer * head )
{
struct list_head * pos ;
bool done = true ;
down_read ( & tomoyo_globally_readable_list_lock ) ;
list_for_each_cookie ( pos , head - > read_var2 ,
& tomoyo_globally_readable_list ) {
struct tomoyo_globally_readable_file_entry * ptr ;
ptr = list_entry ( pos ,
struct tomoyo_globally_readable_file_entry ,
list ) ;
if ( ptr - > is_deleted )
continue ;
2009-06-02 20:42:24 +09:00
done = tomoyo_io_printf ( head , TOMOYO_KEYWORD_ALLOW_READ " %s \n " ,
ptr - > filename - > name ) ;
if ( ! done )
File operation restriction part.
This file controls file related operations of TOMOYO Linux.
tomoyo/tomoyo.c calls the following six functions in this file.
Each function handles the following access types.
* tomoyo_check_file_perm
sysctl()'s "read" and "write".
* tomoyo_check_exec_perm
"execute".
* tomoyo_check_open_permission
open(2) for "read" and "write".
* tomoyo_check_1path_perm
"create", "unlink", "mkdir", "rmdir", "mkfifo",
"mksock", "mkblock", "mkchar", "truncate" and "symlink".
* tomoyo_check_2path_perm
"rename" and "unlink".
* tomoyo_check_rewrite_permission
"rewrite".
("rewrite" are operations which may lose already recorded data of a file,
i.e. open(!O_APPEND) || open(O_TRUNC) || truncate() || ftruncate())
The functions which actually checks ACLs are the following three functions.
Each function handles the following access types.
ACL directive is expressed by "allow_<access type>".
* tomoyo_check_file_acl
Open() operation and execve() operation.
("read", "write", "read/write" and "execute")
* tomoyo_check_single_write_acl
Directory modification operations with 1 pathname.
("create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock",
"mkblock", "mkchar", "truncate", "symlink" and "rewrite")
* tomoyo_check_double_write_acl
Directory modification operations with 2 pathname.
("link" and "rename")
Also, this file contains handlers of some utility directives
for file related operations.
* "allow_read": specifies globally (for all domains) readable files.
* "path_group": specifies pathname macro.
* "deny_rewrite": restricts rewrite operation.
Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Toshiharu Harada <haradats@nttdata.co.jp>
Signed-off-by: James Morris <jmorris@namei.org>
2009-02-05 17:18:14 +09:00
break ;
}
up_read ( & tomoyo_globally_readable_list_lock ) ;
return done ;
}
2009-06-08 12:37:39 +09:00
/* tomoyo_pattern_list is used for holding list of pathnames which are used for
* converting pathnames to pathname patterns during learning mode .
*
* An entry is added by
*
* # echo ' file_pattern / proc / \ $ / mounts ' > \
* / sys / kernel / security / tomoyo / exception_policy
*
* and is deleted by
*
* # echo ' delete file_pattern / proc / \ $ / mounts ' > \
* / sys / kernel / security / tomoyo / exception_policy
*
* and all entries are retrieved by
*
* # grep ^ file_pattern / sys / kernel / security / tomoyo / exception_policy
*
* In the example above , if a process which belongs to a domain which is in
* learning mode requested open ( " /proc/1/mounts " , O_RDONLY ) ,
* " allow_read /proc/ \ $/mounts " is automatically added to the domain which that
* process belongs to .
*
* It is not a desirable behavior that we have to use / proc / \ $ / instead of
* / proc / self / when current process needs to access only current process ' s
* information . As of now , LSM version of TOMOYO is using __d_path ( ) for
* calculating pathname . Non LSM version of TOMOYO is using its own function
* which pretends as if / proc / self / is not a symlink ; so that we can forbid
* current process from accessing other process ' s information .
*/
File operation restriction part.
This file controls file related operations of TOMOYO Linux.
tomoyo/tomoyo.c calls the following six functions in this file.
Each function handles the following access types.
* tomoyo_check_file_perm
sysctl()'s "read" and "write".
* tomoyo_check_exec_perm
"execute".
* tomoyo_check_open_permission
open(2) for "read" and "write".
* tomoyo_check_1path_perm
"create", "unlink", "mkdir", "rmdir", "mkfifo",
"mksock", "mkblock", "mkchar", "truncate" and "symlink".
* tomoyo_check_2path_perm
"rename" and "unlink".
* tomoyo_check_rewrite_permission
"rewrite".
("rewrite" are operations which may lose already recorded data of a file,
i.e. open(!O_APPEND) || open(O_TRUNC) || truncate() || ftruncate())
The functions which actually checks ACLs are the following three functions.
Each function handles the following access types.
ACL directive is expressed by "allow_<access type>".
* tomoyo_check_file_acl
Open() operation and execve() operation.
("read", "write", "read/write" and "execute")
* tomoyo_check_single_write_acl
Directory modification operations with 1 pathname.
("create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock",
"mkblock", "mkchar", "truncate", "symlink" and "rewrite")
* tomoyo_check_double_write_acl
Directory modification operations with 2 pathname.
("link" and "rename")
Also, this file contains handlers of some utility directives
for file related operations.
* "allow_read": specifies globally (for all domains) readable files.
* "path_group": specifies pathname macro.
* "deny_rewrite": restricts rewrite operation.
Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Toshiharu Harada <haradats@nttdata.co.jp>
Signed-off-by: James Morris <jmorris@namei.org>
2009-02-05 17:18:14 +09:00
static LIST_HEAD ( tomoyo_pattern_list ) ;
static DECLARE_RWSEM ( tomoyo_pattern_list_lock ) ;
/**
* tomoyo_update_file_pattern_entry - Update " struct tomoyo_pattern_entry " list .
*
* @ pattern : Pathname pattern .
* @ is_delete : True if it is a delete request .
*
* Returns 0 on success , negative value otherwise .
*/
static int tomoyo_update_file_pattern_entry ( const char * pattern ,
const bool is_delete )
{
struct tomoyo_pattern_entry * new_entry ;
struct tomoyo_pattern_entry * ptr ;
const struct tomoyo_path_info * saved_pattern ;
int error = - ENOMEM ;
if ( ! tomoyo_is_correct_path ( pattern , 0 , 1 , 0 , __func__ ) )
return - EINVAL ;
saved_pattern = tomoyo_save_name ( pattern ) ;
if ( ! saved_pattern )
return - ENOMEM ;
down_write ( & tomoyo_pattern_list_lock ) ;
list_for_each_entry ( ptr , & tomoyo_pattern_list , list ) {
if ( saved_pattern ! = ptr - > pattern )
continue ;
ptr - > is_deleted = is_delete ;
error = 0 ;
goto out ;
}
if ( is_delete ) {
error = - ENOENT ;
goto out ;
}
new_entry = tomoyo_alloc_element ( sizeof ( * new_entry ) ) ;
if ( ! new_entry )
goto out ;
new_entry - > pattern = saved_pattern ;
list_add_tail ( & new_entry - > list , & tomoyo_pattern_list ) ;
error = 0 ;
out :
up_write ( & tomoyo_pattern_list_lock ) ;
return error ;
}
/**
* tomoyo_get_file_pattern - Get patterned pathname .
*
* @ filename : The filename to find patterned pathname .
*
* Returns pointer to pathname pattern if matched , @ filename otherwise .
*/
static const struct tomoyo_path_info *
tomoyo_get_file_pattern ( const struct tomoyo_path_info * filename )
{
struct tomoyo_pattern_entry * ptr ;
const struct tomoyo_path_info * pattern = NULL ;
down_read ( & tomoyo_pattern_list_lock ) ;
list_for_each_entry ( ptr , & tomoyo_pattern_list , list ) {
if ( ptr - > is_deleted )
continue ;
if ( ! tomoyo_path_matches_pattern ( filename , ptr - > pattern ) )
continue ;
pattern = ptr - > pattern ;
if ( tomoyo_strendswith ( pattern - > name , " / \\ * " ) ) {
/* Do nothing. Try to find the better match. */
} else {
/* This would be the better match. Use this. */
break ;
}
}
up_read ( & tomoyo_pattern_list_lock ) ;
if ( pattern )
filename = pattern ;
return filename ;
}
/**
* tomoyo_write_pattern_policy - Write " struct tomoyo_pattern_entry " list .
*
* @ data : String to parse .
* @ is_delete : True if it is a delete request .
*
* Returns 0 on success , negative value otherwise .
*/
int tomoyo_write_pattern_policy ( char * data , const bool is_delete )
{
return tomoyo_update_file_pattern_entry ( data , is_delete ) ;
}
/**
* tomoyo_read_file_pattern - Read " struct tomoyo_pattern_entry " list .
*
* @ head : Pointer to " struct tomoyo_io_buffer " .
*
* Returns true on success , false otherwise .
*/
bool tomoyo_read_file_pattern ( struct tomoyo_io_buffer * head )
{
struct list_head * pos ;
bool done = true ;
down_read ( & tomoyo_pattern_list_lock ) ;
list_for_each_cookie ( pos , head - > read_var2 , & tomoyo_pattern_list ) {
struct tomoyo_pattern_entry * ptr ;
ptr = list_entry ( pos , struct tomoyo_pattern_entry , list ) ;
if ( ptr - > is_deleted )
continue ;
2009-06-02 20:42:24 +09:00
done = tomoyo_io_printf ( head , TOMOYO_KEYWORD_FILE_PATTERN
" %s \n " , ptr - > pattern - > name ) ;
if ( ! done )
File operation restriction part.
This file controls file related operations of TOMOYO Linux.
tomoyo/tomoyo.c calls the following six functions in this file.
Each function handles the following access types.
* tomoyo_check_file_perm
sysctl()'s "read" and "write".
* tomoyo_check_exec_perm
"execute".
* tomoyo_check_open_permission
open(2) for "read" and "write".
* tomoyo_check_1path_perm
"create", "unlink", "mkdir", "rmdir", "mkfifo",
"mksock", "mkblock", "mkchar", "truncate" and "symlink".
* tomoyo_check_2path_perm
"rename" and "unlink".
* tomoyo_check_rewrite_permission
"rewrite".
("rewrite" are operations which may lose already recorded data of a file,
i.e. open(!O_APPEND) || open(O_TRUNC) || truncate() || ftruncate())
The functions which actually checks ACLs are the following three functions.
Each function handles the following access types.
ACL directive is expressed by "allow_<access type>".
* tomoyo_check_file_acl
Open() operation and execve() operation.
("read", "write", "read/write" and "execute")
* tomoyo_check_single_write_acl
Directory modification operations with 1 pathname.
("create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock",
"mkblock", "mkchar", "truncate", "symlink" and "rewrite")
* tomoyo_check_double_write_acl
Directory modification operations with 2 pathname.
("link" and "rename")
Also, this file contains handlers of some utility directives
for file related operations.
* "allow_read": specifies globally (for all domains) readable files.
* "path_group": specifies pathname macro.
* "deny_rewrite": restricts rewrite operation.
Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Toshiharu Harada <haradats@nttdata.co.jp>
Signed-off-by: James Morris <jmorris@namei.org>
2009-02-05 17:18:14 +09:00
break ;
}
up_read ( & tomoyo_pattern_list_lock ) ;
return done ;
}
2009-06-08 12:37:39 +09:00
/*
* tomoyo_no_rewrite_list is used for holding list of pathnames which are by
* default forbidden to modify already written content of a file .
*
* An entry is added by
*
* # echo ' deny_rewrite / var / log / messages ' > \
* / sys / kernel / security / tomoyo / exception_policy
*
* and is deleted by
*
* # echo ' delete deny_rewrite / var / log / messages ' > \
* / sys / kernel / security / tomoyo / exception_policy
*
* and all entries are retrieved by
*
* # grep ^ deny_rewrite / sys / kernel / security / tomoyo / exception_policy
*
* In the example above , if a process requested to rewrite / var / log / messages ,
* the process can ' t rewrite unless the domain which that process belongs to
* has " allow_rewrite /var/log/messages " entry .
*
* It is not a desirable behavior that we have to add " \040 (deleted) " suffix
* when we want to allow rewriting already unlink ( ) ed file . As of now ,
* LSM version of TOMOYO is using __d_path ( ) for calculating pathname .
* Non LSM version of TOMOYO is using its own function which doesn ' t append
* " (deleted) " suffix if the file is already unlink ( ) ed ; so that we don ' t
* need to worry whether the file is already unlink ( ) ed or not .
*/
File operation restriction part.
This file controls file related operations of TOMOYO Linux.
tomoyo/tomoyo.c calls the following six functions in this file.
Each function handles the following access types.
* tomoyo_check_file_perm
sysctl()'s "read" and "write".
* tomoyo_check_exec_perm
"execute".
* tomoyo_check_open_permission
open(2) for "read" and "write".
* tomoyo_check_1path_perm
"create", "unlink", "mkdir", "rmdir", "mkfifo",
"mksock", "mkblock", "mkchar", "truncate" and "symlink".
* tomoyo_check_2path_perm
"rename" and "unlink".
* tomoyo_check_rewrite_permission
"rewrite".
("rewrite" are operations which may lose already recorded data of a file,
i.e. open(!O_APPEND) || open(O_TRUNC) || truncate() || ftruncate())
The functions which actually checks ACLs are the following three functions.
Each function handles the following access types.
ACL directive is expressed by "allow_<access type>".
* tomoyo_check_file_acl
Open() operation and execve() operation.
("read", "write", "read/write" and "execute")
* tomoyo_check_single_write_acl
Directory modification operations with 1 pathname.
("create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock",
"mkblock", "mkchar", "truncate", "symlink" and "rewrite")
* tomoyo_check_double_write_acl
Directory modification operations with 2 pathname.
("link" and "rename")
Also, this file contains handlers of some utility directives
for file related operations.
* "allow_read": specifies globally (for all domains) readable files.
* "path_group": specifies pathname macro.
* "deny_rewrite": restricts rewrite operation.
Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Toshiharu Harada <haradats@nttdata.co.jp>
Signed-off-by: James Morris <jmorris@namei.org>
2009-02-05 17:18:14 +09:00
static LIST_HEAD ( tomoyo_no_rewrite_list ) ;
static DECLARE_RWSEM ( tomoyo_no_rewrite_list_lock ) ;
/**
* tomoyo_update_no_rewrite_entry - Update " struct tomoyo_no_rewrite_entry " list .
*
* @ pattern : Pathname pattern that are not rewritable by default .
* @ is_delete : True if it is a delete request .
*
* Returns 0 on success , negative value otherwise .
*/
static int tomoyo_update_no_rewrite_entry ( const char * pattern ,
const bool is_delete )
{
struct tomoyo_no_rewrite_entry * new_entry , * ptr ;
const struct tomoyo_path_info * saved_pattern ;
int error = - ENOMEM ;
if ( ! tomoyo_is_correct_path ( pattern , 0 , 0 , 0 , __func__ ) )
return - EINVAL ;
saved_pattern = tomoyo_save_name ( pattern ) ;
if ( ! saved_pattern )
return - ENOMEM ;
down_write ( & tomoyo_no_rewrite_list_lock ) ;
list_for_each_entry ( ptr , & tomoyo_no_rewrite_list , list ) {
if ( ptr - > pattern ! = saved_pattern )
continue ;
ptr - > is_deleted = is_delete ;
error = 0 ;
goto out ;
}
if ( is_delete ) {
error = - ENOENT ;
goto out ;
}
new_entry = tomoyo_alloc_element ( sizeof ( * new_entry ) ) ;
if ( ! new_entry )
goto out ;
new_entry - > pattern = saved_pattern ;
list_add_tail ( & new_entry - > list , & tomoyo_no_rewrite_list ) ;
error = 0 ;
out :
up_write ( & tomoyo_no_rewrite_list_lock ) ;
return error ;
}
/**
* tomoyo_is_no_rewrite_file - Check if the given pathname is not permitted to be rewrited .
*
* @ filename : Filename to check .
*
* Returns true if @ filename is specified by " deny_rewrite " directive ,
* false otherwise .
*/
static bool tomoyo_is_no_rewrite_file ( const struct tomoyo_path_info * filename )
{
struct tomoyo_no_rewrite_entry * ptr ;
bool found = false ;
down_read ( & tomoyo_no_rewrite_list_lock ) ;
list_for_each_entry ( ptr , & tomoyo_no_rewrite_list , list ) {
if ( ptr - > is_deleted )
continue ;
if ( ! tomoyo_path_matches_pattern ( filename , ptr - > pattern ) )
continue ;
found = true ;
break ;
}
up_read ( & tomoyo_no_rewrite_list_lock ) ;
return found ;
}
/**
* tomoyo_write_no_rewrite_policy - Write " struct tomoyo_no_rewrite_entry " list .
*
* @ data : String to parse .
* @ is_delete : True if it is a delete request .
*
* Returns 0 on success , negative value otherwise .
*/
int tomoyo_write_no_rewrite_policy ( char * data , const bool is_delete )
{
return tomoyo_update_no_rewrite_entry ( data , is_delete ) ;
}
/**
* tomoyo_read_no_rewrite_policy - Read " struct tomoyo_no_rewrite_entry " list .
*
* @ head : Pointer to " struct tomoyo_io_buffer " .
*
* Returns true on success , false otherwise .
*/
bool tomoyo_read_no_rewrite_policy ( struct tomoyo_io_buffer * head )
{
struct list_head * pos ;
bool done = true ;
down_read ( & tomoyo_no_rewrite_list_lock ) ;
list_for_each_cookie ( pos , head - > read_var2 , & tomoyo_no_rewrite_list ) {
struct tomoyo_no_rewrite_entry * ptr ;
ptr = list_entry ( pos , struct tomoyo_no_rewrite_entry , list ) ;
if ( ptr - > is_deleted )
continue ;
2009-06-02 20:42:24 +09:00
done = tomoyo_io_printf ( head , TOMOYO_KEYWORD_DENY_REWRITE
" %s \n " , ptr - > pattern - > name ) ;
if ( ! done )
File operation restriction part.
This file controls file related operations of TOMOYO Linux.
tomoyo/tomoyo.c calls the following six functions in this file.
Each function handles the following access types.
* tomoyo_check_file_perm
sysctl()'s "read" and "write".
* tomoyo_check_exec_perm
"execute".
* tomoyo_check_open_permission
open(2) for "read" and "write".
* tomoyo_check_1path_perm
"create", "unlink", "mkdir", "rmdir", "mkfifo",
"mksock", "mkblock", "mkchar", "truncate" and "symlink".
* tomoyo_check_2path_perm
"rename" and "unlink".
* tomoyo_check_rewrite_permission
"rewrite".
("rewrite" are operations which may lose already recorded data of a file,
i.e. open(!O_APPEND) || open(O_TRUNC) || truncate() || ftruncate())
The functions which actually checks ACLs are the following three functions.
Each function handles the following access types.
ACL directive is expressed by "allow_<access type>".
* tomoyo_check_file_acl
Open() operation and execve() operation.
("read", "write", "read/write" and "execute")
* tomoyo_check_single_write_acl
Directory modification operations with 1 pathname.
("create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock",
"mkblock", "mkchar", "truncate", "symlink" and "rewrite")
* tomoyo_check_double_write_acl
Directory modification operations with 2 pathname.
("link" and "rename")
Also, this file contains handlers of some utility directives
for file related operations.
* "allow_read": specifies globally (for all domains) readable files.
* "path_group": specifies pathname macro.
* "deny_rewrite": restricts rewrite operation.
Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Toshiharu Harada <haradats@nttdata.co.jp>
Signed-off-by: James Morris <jmorris@namei.org>
2009-02-05 17:18:14 +09:00
break ;
}
up_read ( & tomoyo_no_rewrite_list_lock ) ;
return done ;
}
/**
* tomoyo_update_file_acl - Update file ' s read / write / execute ACL .
*
* @ filename : Filename .
* @ perm : Permission ( between 1 to 7 ) .
* @ domain : Pointer to " struct tomoyo_domain_info " .
* @ is_delete : True if it is a delete request .
*
* Returns 0 on success , negative value otherwise .
*
* This is legacy support interface for older policy syntax .
* Current policy syntax uses " allow_read/write " instead of " 6 " ,
* " allow_read " instead of " 4 " , " allow_write " instead of " 2 " ,
* " allow_execute " instead of " 1 " .
*/
static int tomoyo_update_file_acl ( const char * filename , u8 perm ,
struct tomoyo_domain_info * const domain ,
const bool is_delete )
{
if ( perm > 7 | | ! perm ) {
printk ( KERN_DEBUG " %s: Invalid permission '%d %s' \n " ,
__func__ , perm , filename ) ;
return - EINVAL ;
}
if ( filename [ 0 ] ! = ' @ ' & & tomoyo_strendswith ( filename , " / " ) )
/*
* Only ' allow_mkdir ' and ' allow_rmdir ' are valid for
* directory permissions .
*/
return 0 ;
if ( perm & 4 )
tomoyo_update_single_path_acl ( TOMOYO_TYPE_READ_ACL , filename ,
domain , is_delete ) ;
if ( perm & 2 )
tomoyo_update_single_path_acl ( TOMOYO_TYPE_WRITE_ACL , filename ,
domain , is_delete ) ;
if ( perm & 1 )
tomoyo_update_single_path_acl ( TOMOYO_TYPE_EXECUTE_ACL ,
filename , domain , is_delete ) ;
return 0 ;
}
/**
* tomoyo_check_single_path_acl2 - Check permission for single path operation .
*
* @ domain : Pointer to " struct tomoyo_domain_info " .
* @ filename : Filename to check .
* @ perm : Permission .
* @ may_use_pattern : True if patterned ACL is permitted .
*
* Returns 0 on success , - EPERM otherwise .
*/
static int tomoyo_check_single_path_acl2 ( const struct tomoyo_domain_info *
domain ,
const struct tomoyo_path_info *
filename ,
const u16 perm ,
const bool may_use_pattern )
{
struct tomoyo_acl_info * ptr ;
int error = - EPERM ;
down_read ( & tomoyo_domain_acl_info_list_lock ) ;
list_for_each_entry ( ptr , & domain - > acl_info_list , list ) {
struct tomoyo_single_path_acl_record * acl ;
if ( tomoyo_acl_type2 ( ptr ) ! = TOMOYO_TYPE_SINGLE_PATH_ACL )
continue ;
acl = container_of ( ptr , struct tomoyo_single_path_acl_record ,
head ) ;
if ( ! ( acl - > perm & perm ) )
continue ;
if ( may_use_pattern | | ! acl - > filename - > is_patterned ) {
if ( ! tomoyo_path_matches_pattern ( filename ,
acl - > filename ) )
continue ;
} else {
continue ;
}
error = 0 ;
break ;
}
up_read ( & tomoyo_domain_acl_info_list_lock ) ;
return error ;
}
/**
* tomoyo_check_file_acl - Check permission for opening files .
*
* @ domain : Pointer to " struct tomoyo_domain_info " .
* @ filename : Filename to check .
* @ operation : Mode ( " read " or " write " or " read/write " or " execute " ) .
*
* Returns 0 on success , - EPERM otherwise .
*/
static int tomoyo_check_file_acl ( const struct tomoyo_domain_info * domain ,
const struct tomoyo_path_info * filename ,
const u8 operation )
{
u16 perm = 0 ;
if ( ! tomoyo_check_flags ( domain , TOMOYO_MAC_FOR_FILE ) )
return 0 ;
if ( operation = = 6 )
perm = 1 < < TOMOYO_TYPE_READ_WRITE_ACL ;
else if ( operation = = 4 )
perm = 1 < < TOMOYO_TYPE_READ_ACL ;
else if ( operation = = 2 )
perm = 1 < < TOMOYO_TYPE_WRITE_ACL ;
else if ( operation = = 1 )
perm = 1 < < TOMOYO_TYPE_EXECUTE_ACL ;
else
BUG ( ) ;
return tomoyo_check_single_path_acl2 ( domain , filename , perm ,
operation ! = 1 ) ;
}
/**
* tomoyo_check_file_perm2 - Check permission for opening files .
*
* @ domain : Pointer to " struct tomoyo_domain_info " .
* @ filename : Filename to check .
* @ perm : Mode ( " read " or " write " or " read/write " or " execute " ) .
* @ operation : Operation name passed used for verbose mode .
* @ mode : Access control mode .
*
* Returns 0 on success , negative value otherwise .
*/
static int tomoyo_check_file_perm2 ( struct tomoyo_domain_info * const domain ,
const struct tomoyo_path_info * filename ,
const u8 perm , const char * operation ,
const u8 mode )
{
const bool is_enforce = ( mode = = 3 ) ;
const char * msg = " <unknown> " ;
int error = 0 ;
if ( ! filename )
return 0 ;
error = tomoyo_check_file_acl ( domain , filename , perm ) ;
if ( error & & perm = = 4 & &
( domain - > flags & TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ ) = = 0
& & tomoyo_is_globally_readable_file ( filename ) )
error = 0 ;
if ( perm = = 6 )
msg = tomoyo_sp2keyword ( TOMOYO_TYPE_READ_WRITE_ACL ) ;
else if ( perm = = 4 )
msg = tomoyo_sp2keyword ( TOMOYO_TYPE_READ_ACL ) ;
else if ( perm = = 2 )
msg = tomoyo_sp2keyword ( TOMOYO_TYPE_WRITE_ACL ) ;
else if ( perm = = 1 )
msg = tomoyo_sp2keyword ( TOMOYO_TYPE_EXECUTE_ACL ) ;
else
BUG ( ) ;
if ( ! error )
return 0 ;
if ( tomoyo_verbose_mode ( domain ) )
printk ( KERN_WARNING " TOMOYO-%s: Access '%s(%s) %s' denied "
" for %s \n " , tomoyo_get_msg ( is_enforce ) , msg , operation ,
filename - > name , tomoyo_get_last_name ( domain ) ) ;
if ( is_enforce )
return error ;
if ( mode = = 1 & & tomoyo_domain_quota_is_ok ( domain ) ) {
/* Don't use patterns for execute permission. */
const struct tomoyo_path_info * patterned_file = ( perm ! = 1 ) ?
tomoyo_get_file_pattern ( filename ) : filename ;
tomoyo_update_file_acl ( patterned_file - > name , perm ,
domain , false ) ;
}
return 0 ;
}
/**
* tomoyo_write_file_policy - Update file related list .
*
* @ data : String to parse .
* @ domain : Pointer to " struct tomoyo_domain_info " .
* @ is_delete : True if it is a delete request .
*
* Returns 0 on success , negative value otherwise .
*/
int tomoyo_write_file_policy ( char * data , struct tomoyo_domain_info * domain ,
const bool is_delete )
{
char * filename = strchr ( data , ' ' ) ;
char * filename2 ;
unsigned int perm ;
u8 type ;
if ( ! filename )
return - EINVAL ;
* filename + + = ' \0 ' ;
if ( sscanf ( data , " %u " , & perm ) = = 1 )
return tomoyo_update_file_acl ( filename , ( u8 ) perm , domain ,
is_delete ) ;
if ( strncmp ( data , " allow_ " , 6 ) )
goto out ;
data + = 6 ;
for ( type = 0 ; type < TOMOYO_MAX_SINGLE_PATH_OPERATION ; type + + ) {
if ( strcmp ( data , tomoyo_sp_keyword [ type ] ) )
continue ;
return tomoyo_update_single_path_acl ( type , filename ,
domain , is_delete ) ;
}
filename2 = strchr ( filename , ' ' ) ;
if ( ! filename2 )
goto out ;
* filename2 + + = ' \0 ' ;
for ( type = 0 ; type < TOMOYO_MAX_DOUBLE_PATH_OPERATION ; type + + ) {
if ( strcmp ( data , tomoyo_dp_keyword [ type ] ) )
continue ;
return tomoyo_update_double_path_acl ( type , filename , filename2 ,
domain , is_delete ) ;
}
out :
return - EINVAL ;
}
/**
* tomoyo_update_single_path_acl - Update " struct tomoyo_single_path_acl_record " list .
*
* @ type : Type of operation .
* @ filename : Filename .
* @ domain : Pointer to " struct tomoyo_domain_info " .
* @ is_delete : True if it is a delete request .
*
* Returns 0 on success , negative value otherwise .
*/
static int tomoyo_update_single_path_acl ( const u8 type , const char * filename ,
struct tomoyo_domain_info *
const domain , const bool is_delete )
{
static const u16 rw_mask =
( 1 < < TOMOYO_TYPE_READ_ACL ) | ( 1 < < TOMOYO_TYPE_WRITE_ACL ) ;
const struct tomoyo_path_info * saved_filename ;
struct tomoyo_acl_info * ptr ;
struct tomoyo_single_path_acl_record * acl ;
int error = - ENOMEM ;
const u16 perm = 1 < < type ;
if ( ! domain )
return - EINVAL ;
if ( ! tomoyo_is_correct_path ( filename , 0 , 0 , 0 , __func__ ) )
return - EINVAL ;
saved_filename = tomoyo_save_name ( filename ) ;
if ( ! saved_filename )
return - ENOMEM ;
down_write ( & tomoyo_domain_acl_info_list_lock ) ;
if ( is_delete )
goto delete ;
list_for_each_entry ( ptr , & domain - > acl_info_list , list ) {
if ( tomoyo_acl_type1 ( ptr ) ! = TOMOYO_TYPE_SINGLE_PATH_ACL )
continue ;
acl = container_of ( ptr , struct tomoyo_single_path_acl_record ,
head ) ;
if ( acl - > filename ! = saved_filename )
continue ;
/* Special case. Clear all bits if marked as deleted. */
if ( ptr - > type & TOMOYO_ACL_DELETED )
acl - > perm = 0 ;
acl - > perm | = perm ;
if ( ( acl - > perm & rw_mask ) = = rw_mask )
acl - > perm | = 1 < < TOMOYO_TYPE_READ_WRITE_ACL ;
else if ( acl - > perm & ( 1 < < TOMOYO_TYPE_READ_WRITE_ACL ) )
acl - > perm | = rw_mask ;
ptr - > type & = ~ TOMOYO_ACL_DELETED ;
error = 0 ;
goto out ;
}
/* Not found. Append it to the tail. */
acl = tomoyo_alloc_acl_element ( TOMOYO_TYPE_SINGLE_PATH_ACL ) ;
if ( ! acl )
goto out ;
acl - > perm = perm ;
if ( perm = = ( 1 < < TOMOYO_TYPE_READ_WRITE_ACL ) )
acl - > perm | = rw_mask ;
acl - > filename = saved_filename ;
list_add_tail ( & acl - > head . list , & domain - > acl_info_list ) ;
error = 0 ;
goto out ;
delete :
error = - ENOENT ;
list_for_each_entry ( ptr , & domain - > acl_info_list , list ) {
if ( tomoyo_acl_type2 ( ptr ) ! = TOMOYO_TYPE_SINGLE_PATH_ACL )
continue ;
acl = container_of ( ptr , struct tomoyo_single_path_acl_record ,
head ) ;
if ( acl - > filename ! = saved_filename )
continue ;
acl - > perm & = ~ perm ;
if ( ( acl - > perm & rw_mask ) ! = rw_mask )
acl - > perm & = ~ ( 1 < < TOMOYO_TYPE_READ_WRITE_ACL ) ;
else if ( ! ( acl - > perm & ( 1 < < TOMOYO_TYPE_READ_WRITE_ACL ) ) )
acl - > perm & = ~ rw_mask ;
if ( ! acl - > perm )
ptr - > type | = TOMOYO_ACL_DELETED ;
error = 0 ;
break ;
}
out :
up_write ( & tomoyo_domain_acl_info_list_lock ) ;
return error ;
}
/**
* tomoyo_update_double_path_acl - Update " struct tomoyo_double_path_acl_record " list .
*
* @ type : Type of operation .
* @ filename1 : First filename .
* @ filename2 : Second filename .
* @ domain : Pointer to " struct tomoyo_domain_info " .
* @ is_delete : True if it is a delete request .
*
* Returns 0 on success , negative value otherwise .
*/
static int tomoyo_update_double_path_acl ( const u8 type , const char * filename1 ,
const char * filename2 ,
struct tomoyo_domain_info *
const domain , const bool is_delete )
{
const struct tomoyo_path_info * saved_filename1 ;
const struct tomoyo_path_info * saved_filename2 ;
struct tomoyo_acl_info * ptr ;
struct tomoyo_double_path_acl_record * acl ;
int error = - ENOMEM ;
const u8 perm = 1 < < type ;
if ( ! domain )
return - EINVAL ;
if ( ! tomoyo_is_correct_path ( filename1 , 0 , 0 , 0 , __func__ ) | |
! tomoyo_is_correct_path ( filename2 , 0 , 0 , 0 , __func__ ) )
return - EINVAL ;
saved_filename1 = tomoyo_save_name ( filename1 ) ;
saved_filename2 = tomoyo_save_name ( filename2 ) ;
if ( ! saved_filename1 | | ! saved_filename2 )
return - ENOMEM ;
down_write ( & tomoyo_domain_acl_info_list_lock ) ;
if ( is_delete )
goto delete ;
list_for_each_entry ( ptr , & domain - > acl_info_list , list ) {
if ( tomoyo_acl_type1 ( ptr ) ! = TOMOYO_TYPE_DOUBLE_PATH_ACL )
continue ;
acl = container_of ( ptr , struct tomoyo_double_path_acl_record ,
head ) ;
if ( acl - > filename1 ! = saved_filename1 | |
acl - > filename2 ! = saved_filename2 )
continue ;
/* Special case. Clear all bits if marked as deleted. */
if ( ptr - > type & TOMOYO_ACL_DELETED )
acl - > perm = 0 ;
acl - > perm | = perm ;
ptr - > type & = ~ TOMOYO_ACL_DELETED ;
error = 0 ;
goto out ;
}
/* Not found. Append it to the tail. */
acl = tomoyo_alloc_acl_element ( TOMOYO_TYPE_DOUBLE_PATH_ACL ) ;
if ( ! acl )
goto out ;
acl - > perm = perm ;
acl - > filename1 = saved_filename1 ;
acl - > filename2 = saved_filename2 ;
list_add_tail ( & acl - > head . list , & domain - > acl_info_list ) ;
error = 0 ;
goto out ;
delete :
error = - ENOENT ;
list_for_each_entry ( ptr , & domain - > acl_info_list , list ) {
if ( tomoyo_acl_type2 ( ptr ) ! = TOMOYO_TYPE_DOUBLE_PATH_ACL )
continue ;
acl = container_of ( ptr , struct tomoyo_double_path_acl_record ,
head ) ;
if ( acl - > filename1 ! = saved_filename1 | |
acl - > filename2 ! = saved_filename2 )
continue ;
acl - > perm & = ~ perm ;
if ( ! acl - > perm )
ptr - > type | = TOMOYO_ACL_DELETED ;
error = 0 ;
break ;
}
out :
up_write ( & tomoyo_domain_acl_info_list_lock ) ;
return error ;
}
/**
* tomoyo_check_single_path_acl - Check permission for single path operation .
*
* @ domain : Pointer to " struct tomoyo_domain_info " .
* @ type : Type of operation .
* @ filename : Filename to check .
*
* Returns 0 on success , negative value otherwise .
*/
static int tomoyo_check_single_path_acl ( struct tomoyo_domain_info * domain ,
const u8 type ,
const struct tomoyo_path_info * filename )
{
if ( ! tomoyo_check_flags ( domain , TOMOYO_MAC_FOR_FILE ) )
return 0 ;
return tomoyo_check_single_path_acl2 ( domain , filename , 1 < < type , 1 ) ;
}
/**
* tomoyo_check_double_path_acl - Check permission for double path operation .
*
* @ domain : Pointer to " struct tomoyo_domain_info " .
* @ type : Type of operation .
* @ filename1 : First filename to check .
* @ filename2 : Second filename to check .
*
* Returns 0 on success , - EPERM otherwise .
*/
static int tomoyo_check_double_path_acl ( const struct tomoyo_domain_info * domain ,
const u8 type ,
const struct tomoyo_path_info *
filename1 ,
const struct tomoyo_path_info *
filename2 )
{
struct tomoyo_acl_info * ptr ;
const u8 perm = 1 < < type ;
int error = - EPERM ;
if ( ! tomoyo_check_flags ( domain , TOMOYO_MAC_FOR_FILE ) )
return 0 ;
down_read ( & tomoyo_domain_acl_info_list_lock ) ;
list_for_each_entry ( ptr , & domain - > acl_info_list , list ) {
struct tomoyo_double_path_acl_record * acl ;
if ( tomoyo_acl_type2 ( ptr ) ! = TOMOYO_TYPE_DOUBLE_PATH_ACL )
continue ;
acl = container_of ( ptr , struct tomoyo_double_path_acl_record ,
head ) ;
if ( ! ( acl - > perm & perm ) )
continue ;
if ( ! tomoyo_path_matches_pattern ( filename1 , acl - > filename1 ) )
continue ;
if ( ! tomoyo_path_matches_pattern ( filename2 , acl - > filename2 ) )
continue ;
error = 0 ;
break ;
}
up_read ( & tomoyo_domain_acl_info_list_lock ) ;
return error ;
}
/**
* tomoyo_check_single_path_permission2 - Check permission for single path operation .
*
* @ domain : Pointer to " struct tomoyo_domain_info " .
* @ operation : Type of operation .
* @ filename : Filename to check .
* @ mode : Access control mode .
*
* Returns 0 on success , negative value otherwise .
*/
static int tomoyo_check_single_path_permission2 ( struct tomoyo_domain_info *
const domain , u8 operation ,
const struct tomoyo_path_info *
filename , const u8 mode )
{
const char * msg ;
int error ;
const bool is_enforce = ( mode = = 3 ) ;
if ( ! mode )
return 0 ;
next :
error = tomoyo_check_single_path_acl ( domain , operation , filename ) ;
msg = tomoyo_sp2keyword ( operation ) ;
if ( ! error )
goto ok ;
if ( tomoyo_verbose_mode ( domain ) )
printk ( KERN_WARNING " TOMOYO-%s: Access '%s %s' denied for %s \n " ,
tomoyo_get_msg ( is_enforce ) , msg , filename - > name ,
tomoyo_get_last_name ( domain ) ) ;
if ( mode = = 1 & & tomoyo_domain_quota_is_ok ( domain ) ) {
const char * name = tomoyo_get_file_pattern ( filename ) - > name ;
tomoyo_update_single_path_acl ( operation , name , domain , false ) ;
}
if ( ! is_enforce )
error = 0 ;
ok :
/*
* Since " allow_truncate " doesn ' t imply " allow_rewrite " permission ,
* we need to check " allow_rewrite " permission if the filename is
* specified by " deny_rewrite " keyword .
*/
if ( ! error & & operation = = TOMOYO_TYPE_TRUNCATE_ACL & &
tomoyo_is_no_rewrite_file ( filename ) ) {
operation = TOMOYO_TYPE_REWRITE_ACL ;
goto next ;
}
return error ;
}
/**
* tomoyo_check_file_perm - Check permission for sysctl ( ) ' s " read " and " write " .
*
* @ domain : Pointer to " struct tomoyo_domain_info " .
* @ filename : Filename to check .
* @ perm : Mode ( " read " or " write " or " read/write " ) .
* Returns 0 on success , negative value otherwise .
*/
int tomoyo_check_file_perm ( struct tomoyo_domain_info * domain ,
const char * filename , const u8 perm )
{
struct tomoyo_path_info name ;
const u8 mode = tomoyo_check_flags ( domain , TOMOYO_MAC_FOR_FILE ) ;
if ( ! mode )
return 0 ;
name . name = filename ;
tomoyo_fill_path_info ( & name ) ;
return tomoyo_check_file_perm2 ( domain , & name , perm , " sysctl " , mode ) ;
}
/**
* tomoyo_check_exec_perm - Check permission for " execute " .
*
* @ domain : Pointer to " struct tomoyo_domain_info " .
* @ filename : Check permission for " execute " .
*
* Returns 0 on success , negativevalue otherwise .
*/
int tomoyo_check_exec_perm ( struct tomoyo_domain_info * domain ,
2009-06-04 15:14:34 +09:00
const struct tomoyo_path_info * filename )
File operation restriction part.
This file controls file related operations of TOMOYO Linux.
tomoyo/tomoyo.c calls the following six functions in this file.
Each function handles the following access types.
* tomoyo_check_file_perm
sysctl()'s "read" and "write".
* tomoyo_check_exec_perm
"execute".
* tomoyo_check_open_permission
open(2) for "read" and "write".
* tomoyo_check_1path_perm
"create", "unlink", "mkdir", "rmdir", "mkfifo",
"mksock", "mkblock", "mkchar", "truncate" and "symlink".
* tomoyo_check_2path_perm
"rename" and "unlink".
* tomoyo_check_rewrite_permission
"rewrite".
("rewrite" are operations which may lose already recorded data of a file,
i.e. open(!O_APPEND) || open(O_TRUNC) || truncate() || ftruncate())
The functions which actually checks ACLs are the following three functions.
Each function handles the following access types.
ACL directive is expressed by "allow_<access type>".
* tomoyo_check_file_acl
Open() operation and execve() operation.
("read", "write", "read/write" and "execute")
* tomoyo_check_single_write_acl
Directory modification operations with 1 pathname.
("create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock",
"mkblock", "mkchar", "truncate", "symlink" and "rewrite")
* tomoyo_check_double_write_acl
Directory modification operations with 2 pathname.
("link" and "rename")
Also, this file contains handlers of some utility directives
for file related operations.
* "allow_read": specifies globally (for all domains) readable files.
* "path_group": specifies pathname macro.
* "deny_rewrite": restricts rewrite operation.
Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Toshiharu Harada <haradats@nttdata.co.jp>
Signed-off-by: James Morris <jmorris@namei.org>
2009-02-05 17:18:14 +09:00
{
const u8 mode = tomoyo_check_flags ( domain , TOMOYO_MAC_FOR_FILE ) ;
if ( ! mode )
return 0 ;
return tomoyo_check_file_perm2 ( domain , filename , 1 , " do_execve " , mode ) ;
}
/**
* tomoyo_check_open_permission - Check permission for " read " and " write " .
*
* @ domain : Pointer to " struct tomoyo_domain_info " .
* @ path : Pointer to " struct path " .
* @ flag : Flags for open ( ) .
*
* Returns 0 on success , negative value otherwise .
*/
int tomoyo_check_open_permission ( struct tomoyo_domain_info * domain ,
struct path * path , const int flag )
{
const u8 acc_mode = ACC_MODE ( flag ) ;
int error = - ENOMEM ;
struct tomoyo_path_info * buf ;
const u8 mode = tomoyo_check_flags ( domain , TOMOYO_MAC_FOR_FILE ) ;
const bool is_enforce = ( mode = = 3 ) ;
if ( ! mode | | ! path - > mnt )
return 0 ;
if ( acc_mode = = 0 )
return 0 ;
if ( path - > dentry - > d_inode & & S_ISDIR ( path - > dentry - > d_inode - > i_mode ) )
/*
* I don ' t check directories here because mkdir ( ) and rmdir ( )
* don ' t call me .
*/
return 0 ;
buf = tomoyo_get_path ( path ) ;
if ( ! buf )
goto out ;
error = 0 ;
/*
* If the filename is specified by " deny_rewrite " keyword ,
* we need to check " allow_rewrite " permission when the filename is not
* opened for append mode or the filename is truncated at open time .
*/
if ( ( acc_mode & MAY_WRITE ) & &
( ( flag & O_TRUNC ) | | ! ( flag & O_APPEND ) ) & &
( tomoyo_is_no_rewrite_file ( buf ) ) ) {
error = tomoyo_check_single_path_permission2 ( domain ,
TOMOYO_TYPE_REWRITE_ACL ,
buf , mode ) ;
}
if ( ! error )
error = tomoyo_check_file_perm2 ( domain , buf , acc_mode , " open " ,
mode ) ;
if ( ! error & & ( flag & O_TRUNC ) )
error = tomoyo_check_single_path_permission2 ( domain ,
TOMOYO_TYPE_TRUNCATE_ACL ,
buf , mode ) ;
out :
tomoyo_free ( buf ) ;
if ( ! is_enforce )
error = 0 ;
return error ;
}
/**
* tomoyo_check_1path_perm - Check permission for " create " , " unlink " , " mkdir " , " rmdir " , " mkfifo " , " mksock " , " mkblock " , " mkchar " , " truncate " and " symlink " .
*
* @ domain : Pointer to " struct tomoyo_domain_info " .
* @ operation : Type of operation .
* @ path : Pointer to " struct path " .
*
* Returns 0 on success , negative value otherwise .
*/
int tomoyo_check_1path_perm ( struct tomoyo_domain_info * domain ,
const u8 operation , struct path * path )
{
int error = - ENOMEM ;
struct tomoyo_path_info * buf ;
const u8 mode = tomoyo_check_flags ( domain , TOMOYO_MAC_FOR_FILE ) ;
const bool is_enforce = ( mode = = 3 ) ;
if ( ! mode | | ! path - > mnt )
return 0 ;
buf = tomoyo_get_path ( path ) ;
if ( ! buf )
goto out ;
switch ( operation ) {
case TOMOYO_TYPE_MKDIR_ACL :
case TOMOYO_TYPE_RMDIR_ACL :
if ( ! buf - > is_dir ) {
/*
* tomoyo_get_path ( ) reserves space for appending " /. "
*/
strcat ( ( char * ) buf - > name , " / " ) ;
tomoyo_fill_path_info ( buf ) ;
}
}
error = tomoyo_check_single_path_permission2 ( domain , operation , buf ,
mode ) ;
out :
tomoyo_free ( buf ) ;
if ( ! is_enforce )
error = 0 ;
return error ;
}
/**
* tomoyo_check_rewrite_permission - Check permission for " rewrite " .
*
* @ domain : Pointer to " struct tomoyo_domain_info " .
* @ filp : Pointer to " struct file " .
*
* Returns 0 on success , negative value otherwise .
*/
int tomoyo_check_rewrite_permission ( struct tomoyo_domain_info * domain ,
struct file * filp )
{
int error = - ENOMEM ;
const u8 mode = tomoyo_check_flags ( domain , TOMOYO_MAC_FOR_FILE ) ;
const bool is_enforce = ( mode = = 3 ) ;
struct tomoyo_path_info * buf ;
if ( ! mode | | ! filp - > f_path . mnt )
return 0 ;
buf = tomoyo_get_path ( & filp - > f_path ) ;
if ( ! buf )
goto out ;
if ( ! tomoyo_is_no_rewrite_file ( buf ) ) {
error = 0 ;
goto out ;
}
error = tomoyo_check_single_path_permission2 ( domain ,
TOMOYO_TYPE_REWRITE_ACL ,
buf , mode ) ;
out :
tomoyo_free ( buf ) ;
if ( ! is_enforce )
error = 0 ;
return error ;
}
/**
* tomoyo_check_2path_perm - Check permission for " rename " and " link " .
*
* @ domain : Pointer to " struct tomoyo_domain_info " .
* @ operation : Type of operation .
* @ path1 : Pointer to " struct path " .
* @ path2 : Pointer to " struct path " .
*
* Returns 0 on success , negative value otherwise .
*/
int tomoyo_check_2path_perm ( struct tomoyo_domain_info * const domain ,
const u8 operation , struct path * path1 ,
struct path * path2 )
{
int error = - ENOMEM ;
struct tomoyo_path_info * buf1 , * buf2 ;
const u8 mode = tomoyo_check_flags ( domain , TOMOYO_MAC_FOR_FILE ) ;
const bool is_enforce = ( mode = = 3 ) ;
const char * msg ;
if ( ! mode | | ! path1 - > mnt | | ! path2 - > mnt )
return 0 ;
buf1 = tomoyo_get_path ( path1 ) ;
buf2 = tomoyo_get_path ( path2 ) ;
if ( ! buf1 | | ! buf2 )
goto out ;
{
struct dentry * dentry = path1 - > dentry ;
if ( dentry - > d_inode & & S_ISDIR ( dentry - > d_inode - > i_mode ) ) {
/*
* tomoyo_get_path ( ) reserves space for appending " /. "
*/
if ( ! buf1 - > is_dir ) {
strcat ( ( char * ) buf1 - > name , " / " ) ;
tomoyo_fill_path_info ( buf1 ) ;
}
if ( ! buf2 - > is_dir ) {
strcat ( ( char * ) buf2 - > name , " / " ) ;
tomoyo_fill_path_info ( buf2 ) ;
}
}
}
error = tomoyo_check_double_path_acl ( domain , operation , buf1 , buf2 ) ;
msg = tomoyo_dp2keyword ( operation ) ;
if ( ! error )
goto out ;
if ( tomoyo_verbose_mode ( domain ) )
printk ( KERN_WARNING " TOMOYO-%s: Access '%s %s %s' "
" denied for %s \n " , tomoyo_get_msg ( is_enforce ) ,
msg , buf1 - > name , buf2 - > name ,
tomoyo_get_last_name ( domain ) ) ;
if ( mode = = 1 & & tomoyo_domain_quota_is_ok ( domain ) ) {
const char * name1 = tomoyo_get_file_pattern ( buf1 ) - > name ;
const char * name2 = tomoyo_get_file_pattern ( buf2 ) - > name ;
tomoyo_update_double_path_acl ( operation , name1 , name2 , domain ,
false ) ;
}
out :
tomoyo_free ( buf1 ) ;
tomoyo_free ( buf2 ) ;
if ( ! is_enforce )
error = 0 ;
return error ;
}