2010-05-17 05:10:31 +04:00
/*
* security / tomoyo / mount . c
*
2011-07-14 09:46:51 +04:00
* Copyright ( C ) 2005 - 2011 NTT DATA CORPORATION
2010-05-17 05:10:31 +04:00
*/
# include <linux/slab.h>
# include "common.h"
2011-06-26 18:16:03 +04:00
/* String table for special mount operations. */
static const char * const tomoyo_mounts [ TOMOYO_MAX_SPECIAL_MOUNT ] = {
[ TOMOYO_MOUNT_BIND ] = " --bind " ,
[ TOMOYO_MOUNT_MOVE ] = " --move " ,
[ TOMOYO_MOUNT_REMOUNT ] = " --remount " ,
[ TOMOYO_MOUNT_MAKE_UNBINDABLE ] = " --make-unbindable " ,
[ TOMOYO_MOUNT_MAKE_PRIVATE ] = " --make-private " ,
[ TOMOYO_MOUNT_MAKE_SLAVE ] = " --make-slave " ,
[ TOMOYO_MOUNT_MAKE_SHARED ] = " --make-shared " ,
} ;
2010-05-17 05:10:31 +04:00
2010-06-16 11:22:51 +04:00
/**
* tomoyo_audit_mount_log - Audit mount log .
*
* @ r : Pointer to " struct tomoyo_request_info " .
*
* Returns 0 on success , negative value otherwise .
*/
static int tomoyo_audit_mount_log ( struct tomoyo_request_info * r )
{
2011-06-26 18:18:58 +04:00
return tomoyo_supervisor ( r , " file mount %s %s %s 0x%lX \n " ,
2011-06-26 18:15:31 +04:00
r - > param . mount . dev - > name ,
2011-06-26 18:18:58 +04:00
r - > param . mount . dir - > name ,
r - > param . mount . type - > name ,
r - > param . mount . flags ) ;
2010-06-16 11:22:51 +04:00
}
2011-06-26 18:16:36 +04:00
/**
* tomoyo_check_mount_acl - Check permission for path path path number operation .
*
* @ r : Pointer to " struct tomoyo_request_info " .
* @ ptr : Pointer to " struct tomoyo_acl_info " .
*
* Returns true if granted , false otherwise .
*/
2010-07-29 09:29:55 +04:00
static bool tomoyo_check_mount_acl ( struct tomoyo_request_info * r ,
2010-06-16 11:22:51 +04:00
const struct tomoyo_acl_info * ptr )
{
const struct tomoyo_mount_acl * acl =
container_of ( ptr , typeof ( * acl ) , head ) ;
2011-06-26 18:16:36 +04:00
return tomoyo_compare_number_union ( r - > param . mount . flags ,
& acl - > flags ) & &
tomoyo_compare_name_union ( r - > param . mount . type ,
& acl - > fs_type ) & &
tomoyo_compare_name_union ( r - > param . mount . dir ,
& acl - > dir_name ) & &
2010-06-16 11:22:51 +04:00
( ! r - > param . mount . need_dev | |
2011-06-26 18:16:36 +04:00
tomoyo_compare_name_union ( r - > param . mount . dev ,
& acl - > dev_name ) ) ;
2010-06-16 11:22:51 +04:00
}
2010-05-17 05:10:31 +04:00
/**
2010-06-16 11:24:58 +04:00
* tomoyo_mount_acl - Check permission for mount ( ) operation .
2010-05-17 05:10:31 +04:00
*
* @ r : Pointer to " struct tomoyo_request_info " .
2011-07-14 09:46:51 +04:00
* @ dev_name : Name of device file . Maybe NULL .
2010-05-17 05:10:31 +04:00
* @ dir : Pointer to " struct path " .
* @ type : Name of filesystem type .
* @ flags : Mount options .
*
* Returns 0 on success , negative value otherwise .
*
* Caller holds tomoyo_read_lock ( ) .
*/
2010-06-16 11:24:58 +04:00
static int tomoyo_mount_acl ( struct tomoyo_request_info * r , char * dev_name ,
2011-06-26 18:16:03 +04:00
struct path * dir , const char * type ,
unsigned long flags )
2010-05-17 05:10:31 +04:00
{
2011-07-08 08:25:53 +04:00
struct tomoyo_obj_info obj = { } ;
2010-05-17 05:10:31 +04:00
struct path path ;
struct file_system_type * fstype = NULL ;
const char * requested_type = NULL ;
const char * requested_dir_name = NULL ;
const char * requested_dev_name = NULL ;
struct tomoyo_path_info rtype ;
struct tomoyo_path_info rdev ;
struct tomoyo_path_info rdir ;
int need_dev = 0 ;
int error = - ENOMEM ;
2011-07-08 08:25:53 +04:00
r - > obj = & obj ;
2010-05-17 05:10:31 +04:00
/* Get fstype. */
2010-06-03 15:36:43 +04:00
requested_type = tomoyo_encode ( type ) ;
2010-05-17 05:10:31 +04:00
if ( ! requested_type )
goto out ;
rtype . name = requested_type ;
tomoyo_fill_path_info ( & rtype ) ;
/* Get mount point. */
2011-07-08 08:25:53 +04:00
obj . path2 = * dir ;
2010-05-17 05:10:31 +04:00
requested_dir_name = tomoyo_realpath_from_path ( dir ) ;
if ( ! requested_dir_name ) {
error = - ENOMEM ;
goto out ;
}
rdir . name = requested_dir_name ;
tomoyo_fill_path_info ( & rdir ) ;
/* Compare fs name. */
2011-06-26 18:16:03 +04:00
if ( type = = tomoyo_mounts [ TOMOYO_MOUNT_REMOUNT ] ) {
2010-05-17 05:10:31 +04:00
/* dev_name is ignored. */
2011-06-26 18:16:03 +04:00
} else if ( type = = tomoyo_mounts [ TOMOYO_MOUNT_MAKE_UNBINDABLE ] | |
type = = tomoyo_mounts [ TOMOYO_MOUNT_MAKE_PRIVATE ] | |
type = = tomoyo_mounts [ TOMOYO_MOUNT_MAKE_SLAVE ] | |
type = = tomoyo_mounts [ TOMOYO_MOUNT_MAKE_SHARED ] ) {
2010-05-17 05:10:31 +04:00
/* dev_name is ignored. */
2011-06-26 18:16:03 +04:00
} else if ( type = = tomoyo_mounts [ TOMOYO_MOUNT_BIND ] | |
type = = tomoyo_mounts [ TOMOYO_MOUNT_MOVE ] ) {
2010-05-17 05:10:31 +04:00
need_dev = - 1 ; /* dev_name is a directory */
} else {
fstype = get_fs_type ( type ) ;
if ( ! fstype ) {
error = - ENODEV ;
goto out ;
}
if ( fstype - > fs_flags & FS_REQUIRES_DEV )
/* dev_name is a block device file. */
need_dev = 1 ;
}
if ( need_dev ) {
/* Get mount point or device file. */
2011-06-13 08:49:11 +04:00
if ( ! dev_name | | kern_path ( dev_name , LOOKUP_FOLLOW , & path ) ) {
2010-05-17 05:10:31 +04:00
error = - ENOENT ;
goto out ;
}
2011-07-08 08:25:53 +04:00
obj . path1 = path ;
2010-05-17 05:10:31 +04:00
requested_dev_name = tomoyo_realpath_from_path ( & path ) ;
if ( ! requested_dev_name ) {
error = - ENOENT ;
goto out ;
}
} else {
/* Map dev_name to "<NULL>" if no dev_name given. */
if ( ! dev_name )
dev_name = " <NULL> " ;
2010-06-03 15:36:43 +04:00
requested_dev_name = tomoyo_encode ( dev_name ) ;
2010-05-17 05:10:31 +04:00
if ( ! requested_dev_name ) {
error = - ENOMEM ;
goto out ;
}
}
rdev . name = requested_dev_name ;
tomoyo_fill_path_info ( & rdev ) ;
2010-06-16 11:21:36 +04:00
r - > param_type = TOMOYO_TYPE_MOUNT_ACL ;
r - > param . mount . need_dev = need_dev ;
r - > param . mount . dev = & rdev ;
r - > param . mount . dir = & rdir ;
r - > param . mount . type = & rtype ;
r - > param . mount . flags = flags ;
2010-06-16 11:22:51 +04:00
do {
tomoyo_check_acl ( r , tomoyo_check_mount_acl ) ;
error = tomoyo_audit_mount_log ( r ) ;
} while ( error = = TOMOYO_RETRY_REQUEST ) ;
2010-05-17 05:10:31 +04:00
out :
kfree ( requested_dev_name ) ;
kfree ( requested_dir_name ) ;
if ( fstype )
put_filesystem ( fstype ) ;
kfree ( requested_type ) ;
2011-07-08 08:25:53 +04:00
/* Drop refcount obtained by kern_path(). */
if ( obj . path1 . dentry )
path_put ( & obj . path1 ) ;
2010-05-17 05:10:31 +04:00
return error ;
}
/**
* tomoyo_mount_permission - Check permission for mount ( ) operation .
*
2011-07-14 09:46:51 +04:00
* @ dev_name : Name of device file . Maybe NULL .
2010-05-17 05:10:31 +04:00
* @ path : Pointer to " struct path " .
2011-07-14 09:46:51 +04:00
* @ type : Name of filesystem type . Maybe NULL .
2010-05-17 05:10:31 +04:00
* @ flags : Mount options .
2011-07-14 09:46:51 +04:00
* @ data_page : Optional data . Maybe NULL .
2010-05-17 05:10:31 +04:00
*
* Returns 0 on success , negative value otherwise .
*/
2011-06-26 18:16:03 +04:00
int tomoyo_mount_permission ( char * dev_name , struct path * path ,
const char * type , unsigned long flags ,
void * data_page )
2010-05-17 05:10:31 +04:00
{
struct tomoyo_request_info r ;
int error ;
int idx ;
2010-06-03 15:38:44 +04:00
if ( tomoyo_init_request_info ( & r , NULL , TOMOYO_MAC_FILE_MOUNT )
= = TOMOYO_CONFIG_DISABLED )
2010-05-17 05:10:31 +04:00
return 0 ;
2010-06-16 11:24:58 +04:00
if ( ( flags & MS_MGC_MSK ) = = MS_MGC_VAL )
flags & = ~ MS_MGC_MSK ;
if ( flags & MS_REMOUNT ) {
2011-06-26 18:16:03 +04:00
type = tomoyo_mounts [ TOMOYO_MOUNT_REMOUNT ] ;
2010-06-16 11:24:58 +04:00
flags & = ~ MS_REMOUNT ;
}
if ( flags & MS_MOVE ) {
2011-06-26 18:16:03 +04:00
type = tomoyo_mounts [ TOMOYO_MOUNT_MOVE ] ;
2010-06-16 11:24:58 +04:00
flags & = ~ MS_MOVE ;
}
if ( flags & MS_BIND ) {
2011-06-26 18:16:03 +04:00
type = tomoyo_mounts [ TOMOYO_MOUNT_BIND ] ;
2010-06-16 11:24:58 +04:00
flags & = ~ MS_BIND ;
}
if ( flags & MS_UNBINDABLE ) {
2011-06-26 18:16:03 +04:00
type = tomoyo_mounts [ TOMOYO_MOUNT_MAKE_UNBINDABLE ] ;
2010-06-16 11:24:58 +04:00
flags & = ~ MS_UNBINDABLE ;
}
if ( flags & MS_PRIVATE ) {
2011-06-26 18:16:03 +04:00
type = tomoyo_mounts [ TOMOYO_MOUNT_MAKE_PRIVATE ] ;
2010-06-16 11:24:58 +04:00
flags & = ~ MS_PRIVATE ;
}
if ( flags & MS_SLAVE ) {
2011-06-26 18:16:03 +04:00
type = tomoyo_mounts [ TOMOYO_MOUNT_MAKE_SLAVE ] ;
2010-06-16 11:24:58 +04:00
flags & = ~ MS_SLAVE ;
}
if ( flags & MS_SHARED ) {
2011-06-26 18:16:03 +04:00
type = tomoyo_mounts [ TOMOYO_MOUNT_MAKE_SHARED ] ;
2010-06-16 11:24:58 +04:00
flags & = ~ MS_SHARED ;
}
2010-05-17 05:10:31 +04:00
if ( ! type )
type = " <NULL> " ;
idx = tomoyo_read_lock ( ) ;
error = tomoyo_mount_acl ( & r , dev_name , path , type , flags ) ;
tomoyo_read_unlock ( idx ) ;
return error ;
}