TOMOYO: Use callback for permission check.

We can use callback function since parameters are passed via
"const struct tomoyo_request_info".

Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>
This commit is contained in:
Tetsuo Handa 2010-06-16 16:22:51 +09:00 committed by James Morris
parent cf6e9a6468
commit 99a852596b
4 changed files with 230 additions and 258 deletions

View File

@ -952,6 +952,9 @@ int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
*,
const struct tomoyo_acl_head
*));
void tomoyo_check_acl(struct tomoyo_request_info *r,
bool (*check_entry) (const struct tomoyo_request_info *,
const struct tomoyo_acl_info *));
/********** External variable definitions. **********/

View File

@ -109,6 +109,24 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
return error;
}
void tomoyo_check_acl(struct tomoyo_request_info *r,
bool (*check_entry) (const struct tomoyo_request_info *,
const struct tomoyo_acl_info *))
{
const struct tomoyo_domain_info *domain = r->domain;
struct tomoyo_acl_info *ptr;
list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
if (ptr->is_deleted || ptr->type != r->param_type)
continue;
if (check_entry(r, ptr)) {
r->granted = true;
return;
}
}
r->granted = false;
}
/*
* tomoyo_domain_list is used for holding list of domains.
* The ->acl_info_list of "struct tomoyo_domain_info" is used for holding

View File

@ -218,6 +218,108 @@ static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path)
return false;
}
/**
* tomoyo_audit_path_log - Audit path request log.
*
* @r: Pointer to "struct tomoyo_request_info".
*
* Returns 0 on success, negative value otherwise.
*/
static int tomoyo_audit_path_log(struct tomoyo_request_info *r)
{
const char *operation = tomoyo_path_keyword[r->param.path.operation];
const struct tomoyo_path_info *filename = r->param.path.filename;
if (r->granted)
return 0;
tomoyo_warn_log(r, "%s %s", operation, filename->name);
return tomoyo_supervisor(r, "allow_%s %s\n", operation,
tomoyo_file_pattern(filename));
}
/**
* tomoyo_audit_path2_log - Audit path/path request log.
*
* @r: Pointer to "struct tomoyo_request_info".
*
* Returns 0 on success, negative value otherwise.
*/
static int tomoyo_audit_path2_log(struct tomoyo_request_info *r)
{
const char *operation = tomoyo_path2_keyword[r->param.path2.operation];
const struct tomoyo_path_info *filename1 = r->param.path2.filename1;
const struct tomoyo_path_info *filename2 = r->param.path2.filename2;
if (r->granted)
return 0;
tomoyo_warn_log(r, "%s %s %s", operation, filename1->name,
filename2->name);
return tomoyo_supervisor(r, "allow_%s %s %s\n", operation,
tomoyo_file_pattern(filename1),
tomoyo_file_pattern(filename2));
}
/**
* tomoyo_audit_mkdev_log - Audit path/number/number/number request log.
*
* @r: Pointer to "struct tomoyo_request_info".
*
* Returns 0 on success, negative value otherwise.
*/
static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r)
{
const char *operation = tomoyo_path_number32keyword(r->param.mkdev.
operation);
const struct tomoyo_path_info *filename = r->param.mkdev.filename;
const unsigned int major = r->param.mkdev.major;
const unsigned int minor = r->param.mkdev.minor;
const unsigned int mode = r->param.mkdev.mode;
if (r->granted)
return 0;
tomoyo_warn_log(r, "%s %s 0%o %u %u", operation, filename->name, mode,
major, minor);
return tomoyo_supervisor(r, "allow_%s %s 0%o %u %u\n", operation,
tomoyo_file_pattern(filename), mode, major,
minor);
}
/**
* tomoyo_audit_path_number_log - Audit path/number request log.
*
* @r: Pointer to "struct tomoyo_request_info".
* @error: Error code.
*
* Returns 0 on success, negative value otherwise.
*/
static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r)
{
const u8 type = r->param.path_number.operation;
u8 radix;
const struct tomoyo_path_info *filename = r->param.path_number.filename;
const char *operation = tomoyo_path_number_keyword[type];
char buffer[64];
if (r->granted)
return 0;
switch (type) {
case TOMOYO_TYPE_CREATE:
case TOMOYO_TYPE_MKDIR:
case TOMOYO_TYPE_MKFIFO:
case TOMOYO_TYPE_MKSOCK:
case TOMOYO_TYPE_CHMOD:
radix = TOMOYO_VALUE_TYPE_OCTAL;
break;
case TOMOYO_TYPE_IOCTL:
radix = TOMOYO_VALUE_TYPE_HEXADECIMAL;
break;
default:
radix = TOMOYO_VALUE_TYPE_DECIMAL;
break;
}
tomoyo_print_ulong(buffer, sizeof(buffer), r->param.path_number.number,
radix);
tomoyo_warn_log(r, "%s %s %s", operation, filename->name, buffer);
return tomoyo_supervisor(r, "allow_%s %s %s\n", operation,
tomoyo_file_pattern(filename), buffer);
}
static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
const char *filename2,
struct tomoyo_domain_info *const domain,
@ -637,37 +739,52 @@ bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head)
return done;
}
/**
* tomoyo_path_acl - Check permission for single path operation.
*
* @r: Pointer to "struct tomoyo_request_info".
* @filename: Filename to check.
* @perm: Permission.
*
* Returns 0 on success, -EPERM otherwise.
*
* Caller holds tomoyo_read_lock().
*/
static int tomoyo_path_acl(const struct tomoyo_request_info *r,
const struct tomoyo_path_info *filename,
const u32 perm)
static bool tomoyo_check_path_acl(const struct tomoyo_request_info *r,
const struct tomoyo_acl_info *ptr)
{
struct tomoyo_domain_info *domain = r->domain;
struct tomoyo_acl_info *ptr;
int error = -EPERM;
const struct tomoyo_path_acl *acl = container_of(ptr, typeof(*acl),
head);
return (acl->perm & (1 << r->param.path.operation)) &&
tomoyo_compare_name_union(r->param.path.filename, &acl->name);
}
list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
struct tomoyo_path_acl *acl;
if (ptr->type != TOMOYO_TYPE_PATH_ACL)
continue;
acl = container_of(ptr, struct tomoyo_path_acl, head);
if (!(acl->perm & perm) ||
!tomoyo_compare_name_union(filename, &acl->name))
continue;
error = 0;
break;
}
return error;
static bool tomoyo_check_path_number_acl(const struct tomoyo_request_info *r,
const struct tomoyo_acl_info *ptr)
{
const struct tomoyo_path_number_acl *acl =
container_of(ptr, typeof(*acl), head);
return (acl->perm & (1 << r->param.path_number.operation)) &&
tomoyo_compare_number_union(r->param.path_number.number,
&acl->number) &&
tomoyo_compare_name_union(r->param.path_number.filename,
&acl->name);
}
static bool tomoyo_check_path2_acl(const struct tomoyo_request_info *r,
const struct tomoyo_acl_info *ptr)
{
const struct tomoyo_path2_acl *acl =
container_of(ptr, typeof(*acl), head);
return (acl->perm & (1 << r->param.path2.operation)) &&
tomoyo_compare_name_union(r->param.path2.filename1, &acl->name1)
&& tomoyo_compare_name_union(r->param.path2.filename2,
&acl->name2);
}
static bool tomoyo_check_mkdev_acl(const struct tomoyo_request_info *r,
const struct tomoyo_acl_info *ptr)
{
const struct tomoyo_path_number3_acl *acl =
container_of(ptr, typeof(*acl), head);
return (acl->perm & (1 << r->param.mkdev.operation)) &&
tomoyo_compare_number_union(r->param.mkdev.mode,
&acl->mode) &&
tomoyo_compare_number_union(r->param.mkdev.major,
&acl->major) &&
tomoyo_compare_number_union(r->param.mkdev.minor,
&acl->minor) &&
tomoyo_compare_name_union(r->param.mkdev.filename,
&acl->name);
}
static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a,
@ -869,88 +986,6 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
return error;
}
/**
* tomoyo_path_number3_acl - Check permission for path/number/number/number operation.
*
* @r: Pointer to "struct tomoyo_request_info".
* @filename: Filename to check.
* @perm: Permission.
* @mode: Create mode.
* @major: Device major number.
* @minor: Device minor number.
*
* Returns 0 on success, -EPERM otherwise.
*
* Caller holds tomoyo_read_lock().
*/
static int tomoyo_path_number3_acl(struct tomoyo_request_info *r,
const struct tomoyo_path_info *filename,
const u16 perm, const unsigned int mode,
const unsigned int major,
const unsigned int minor)
{
struct tomoyo_domain_info *domain = r->domain;
struct tomoyo_acl_info *ptr;
int error = -EPERM;
list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
struct tomoyo_path_number3_acl *acl;
if (ptr->type != TOMOYO_TYPE_PATH_NUMBER3_ACL)
continue;
acl = container_of(ptr, struct tomoyo_path_number3_acl, head);
if (!tomoyo_compare_number_union(mode, &acl->mode))
continue;
if (!tomoyo_compare_number_union(major, &acl->major))
continue;
if (!tomoyo_compare_number_union(minor, &acl->minor))
continue;
if (!(acl->perm & perm))
continue;
if (!tomoyo_compare_name_union(filename, &acl->name))
continue;
error = 0;
break;
}
return error;
}
/**
* tomoyo_path2_acl - Check permission for double path operation.
*
* @r: Pointer to "struct tomoyo_request_info".
* @type: Type of operation.
* @filename1: First filename to check.
* @filename2: Second filename to check.
*
* Returns 0 on success, -EPERM otherwise.
*
* Caller holds tomoyo_read_lock().
*/
static int tomoyo_path2_acl(const struct tomoyo_request_info *r, const u8 type,
const struct tomoyo_path_info *filename1,
const struct tomoyo_path_info *filename2)
{
const struct tomoyo_domain_info *domain = r->domain;
struct tomoyo_acl_info *ptr;
const u8 perm = 1 << type;
int error = -EPERM;
list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
struct tomoyo_path2_acl *acl;
if (ptr->type != TOMOYO_TYPE_PATH2_ACL)
continue;
acl = container_of(ptr, struct tomoyo_path2_acl, head);
if (!(acl->perm & perm))
continue;
if (!tomoyo_compare_name_union(filename1, &acl->name1))
continue;
if (!tomoyo_compare_name_union(filename2, &acl->name2))
continue;
error = 0;
break;
}
return error;
}
/**
* tomoyo_path_permission - Check permission for single path operation.
*
@ -965,7 +1000,6 @@ static int tomoyo_path2_acl(const struct tomoyo_request_info *r, const u8 type,
int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
const struct tomoyo_path_info *filename)
{
const char *msg;
int error;
next:
@ -977,17 +1011,12 @@ int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
r->param.path.filename = filename;
r->param.path.operation = operation;
do {
error = tomoyo_path_acl(r, filename, 1 << operation);
if (error && operation == TOMOYO_TYPE_READ &&
tomoyo_check_acl(r, tomoyo_check_path_acl);
if (!r->granted && operation == TOMOYO_TYPE_READ &&
!r->domain->ignore_global_allow_read &&
tomoyo_is_globally_readable_file(filename))
error = 0;
if (!error)
break;
msg = tomoyo_path2keyword(operation);
tomoyo_warn_log(r, "%s %s", msg, filename->name);
error = tomoyo_supervisor(r, "allow_%s %s\n", msg,
tomoyo_file_pattern(filename));
r->granted = true;
error = tomoyo_audit_path_log(r);
/*
* Do not retry for execute request, for alias may have
* changed.
@ -1007,42 +1036,6 @@ int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
return error;
}
/**
* tomoyo_path_number_acl - Check permission for ioctl/chmod/chown/chgrp operation.
*
* @r: Pointer to "struct tomoyo_request_info".
* @type: Operation.
* @filename: Filename to check.
* @number: Number.
*
* Returns 0 on success, -EPERM otherwise.
*
* Caller holds tomoyo_read_lock().
*/
static int tomoyo_path_number_acl(struct tomoyo_request_info *r, const u8 type,
const struct tomoyo_path_info *filename,
const unsigned long number)
{
struct tomoyo_domain_info *domain = r->domain;
struct tomoyo_acl_info *ptr;
const u8 perm = 1 << type;
int error = -EPERM;
list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
struct tomoyo_path_number_acl *acl;
if (ptr->type != TOMOYO_TYPE_PATH_NUMBER_ACL)
continue;
acl = container_of(ptr, struct tomoyo_path_number_acl,
head);
if (!(acl->perm & perm) ||
!tomoyo_compare_number_union(number, &acl->number) ||
!tomoyo_compare_name_union(filename, &acl->name))
continue;
error = 0;
break;
}
return error;
}
static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a,
const struct tomoyo_acl_info *b)
{
@ -1123,42 +1116,17 @@ static int tomoyo_path_number_perm2(struct tomoyo_request_info *r,
const struct tomoyo_path_info *filename,
const unsigned long number)
{
char buffer[64];
int error;
u8 radix;
const char *msg;
if (!filename)
return 0;
switch (type) {
case TOMOYO_TYPE_CREATE:
case TOMOYO_TYPE_MKDIR:
case TOMOYO_TYPE_MKFIFO:
case TOMOYO_TYPE_MKSOCK:
case TOMOYO_TYPE_CHMOD:
radix = TOMOYO_VALUE_TYPE_OCTAL;
break;
case TOMOYO_TYPE_IOCTL:
radix = TOMOYO_VALUE_TYPE_HEXADECIMAL;
break;
default:
radix = TOMOYO_VALUE_TYPE_DECIMAL;
break;
}
tomoyo_print_ulong(buffer, sizeof(buffer), number, radix);
r->param_type = TOMOYO_TYPE_PATH_NUMBER_ACL;
r->param.path_number.operation = type;
r->param.path_number.filename = filename;
r->param.path_number.number = number;
do {
error = tomoyo_path_number_acl(r, type, filename, number);
if (!error)
break;
msg = tomoyo_path_number2keyword(type);
tomoyo_warn_log(r, "%s %s %s", msg, filename->name, buffer);
error = tomoyo_supervisor(r, "allow_%s %s %s\n", msg,
tomoyo_file_pattern(filename),
buffer);
tomoyo_check_acl(r, tomoyo_check_path_number_acl);
error = tomoyo_audit_path_number_log(r);
} while (error == TOMOYO_RETRY_REQUEST);
return error;
}
@ -1310,47 +1278,6 @@ int tomoyo_path_perm(const u8 operation, struct path *path)
return error;
}
/**
* tomoyo_path_number3_perm2 - Check permission for path/number/number/number operation.
*
* @r: Pointer to "struct tomoyo_request_info".
* @operation: Type of operation.
* @filename: Filename to check.
* @mode: Create mode.
* @dev: Device number.
*
* Returns 0 on success, negative value otherwise.
*
* Caller holds tomoyo_read_lock().
*/
static int tomoyo_path_number3_perm2(struct tomoyo_request_info *r,
const u8 operation,
const struct tomoyo_path_info *filename,
const unsigned int mode,
const unsigned int dev)
{
int error;
const char *msg;
const unsigned int major = MAJOR(dev);
const unsigned int minor = MINOR(dev);
do {
error = tomoyo_path_number3_acl(r, filename, 1 << operation,
mode, major, minor);
if (!error)
break;
msg = tomoyo_path_number32keyword(operation);
tomoyo_warn_log(r, "%s %s 0%o %u %u", msg, filename->name,
mode, major, minor);
error = tomoyo_supervisor(r, "allow_%s %s 0%o %u %u\n", msg,
tomoyo_file_pattern(filename), mode,
major, minor);
} while (error == TOMOYO_RETRY_REQUEST);
if (r->mode != TOMOYO_CONFIG_ENFORCING)
error = 0;
return error;
}
/**
* tomoyo_path_number3_perm - Check permission for "mkblock" and "mkchar".
*
@ -1383,8 +1310,8 @@ int tomoyo_path_number3_perm(const u8 operation, struct path *path,
r.param.mkdev.mode = mode;
r.param.mkdev.major = MAJOR(dev);
r.param.mkdev.minor = MINOR(dev);
error = tomoyo_path_number3_perm2(&r, operation, &buf, mode,
dev);
tomoyo_check_acl(&r, tomoyo_check_mkdev_acl);
error = tomoyo_audit_mkdev_log(&r);
kfree(buf.name);
}
tomoyo_read_unlock(idx);
@ -1406,7 +1333,6 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
struct path *path2)
{
int error = -ENOMEM;
const char *msg;
struct tomoyo_path_info buf1;
struct tomoyo_path_info buf2;
struct tomoyo_request_info r;
@ -1440,15 +1366,9 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
r.param.path2.filename1 = &buf1;
r.param.path2.filename2 = &buf2;
do {
error = tomoyo_path2_acl(&r, operation, &buf1, &buf2);
if (!error)
break;
msg = tomoyo_path22keyword(operation);
tomoyo_warn_log(&r, "%s %s %s", msg, buf1.name, buf2.name);
error = tomoyo_supervisor(&r, "allow_%s %s %s\n", msg,
tomoyo_file_pattern(&buf1),
tomoyo_file_pattern(&buf2));
} while (error == TOMOYO_RETRY_REQUEST);
tomoyo_check_acl(&r, tomoyo_check_path2_acl);
error = tomoyo_audit_path2_log(&r);
} while (error == TOMOYO_RETRY_REQUEST);
out:
kfree(buf1.name);
kfree(buf2.name);

View File

@ -24,6 +24,54 @@
/* Allow to call 'mount --make-shared /dir' */
#define TOMOYO_MOUNT_MAKE_SHARED_KEYWORD "--make-shared"
/**
* 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)
{
const char *dev = r->param.mount.dev->name;
const char *dir = r->param.mount.dir->name;
const char *type = r->param.mount.type->name;
const unsigned long flags = r->param.mount.flags;
if (r->granted)
return 0;
if (!strcmp(type, TOMOYO_MOUNT_REMOUNT_KEYWORD))
tomoyo_warn_log(r, "mount -o remount %s 0x%lX", dir, flags);
else if (!strcmp(type, TOMOYO_MOUNT_BIND_KEYWORD)
|| !strcmp(type, TOMOYO_MOUNT_MOVE_KEYWORD))
tomoyo_warn_log(r, "mount %s %s %s 0x%lX", type, dev, dir,
flags);
else if (!strcmp(type, TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD) ||
!strcmp(type, TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD) ||
!strcmp(type, TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD) ||
!strcmp(type, TOMOYO_MOUNT_MAKE_SHARED_KEYWORD))
tomoyo_warn_log(r, "mount %s %s 0x%lX", type, dir, flags);
else
tomoyo_warn_log(r, "mount -t %s %s %s 0x%lX", type, dev, dir,
flags);
return tomoyo_supervisor(r,
TOMOYO_KEYWORD_ALLOW_MOUNT "%s %s %s 0x%lX\n",
tomoyo_file_pattern(r->param.mount.dev),
tomoyo_file_pattern(r->param.mount.dir), type,
flags);
}
static bool tomoyo_check_mount_acl(const struct tomoyo_request_info *r,
const struct tomoyo_acl_info *ptr)
{
const struct tomoyo_mount_acl *acl =
container_of(ptr, typeof(*acl), head);
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) &&
(!r->param.mount.need_dev ||
tomoyo_compare_name_union(r->param.mount.dev, &acl->dev_name));
}
/**
* tomoyo_mount_acl2 - Check permission for mount() operation.
*
@ -41,7 +89,6 @@ static int tomoyo_mount_acl2(struct tomoyo_request_info *r, char *dev_name,
struct path *dir, char *type, unsigned long flags)
{
struct path path;
struct tomoyo_acl_info *ptr;
struct file_system_type *fstype = NULL;
const char *requested_type = NULL;
const char *requested_dir_name = NULL;
@ -118,26 +165,10 @@ static int tomoyo_mount_acl2(struct tomoyo_request_info *r, char *dev_name,
r->param.mount.dir = &rdir;
r->param.mount.type = &rtype;
r->param.mount.flags = flags;
list_for_each_entry_rcu(ptr, &r->domain->acl_info_list, list) {
struct tomoyo_mount_acl *acl;
if (ptr->is_deleted || ptr->type != TOMOYO_TYPE_MOUNT_ACL)
continue;
acl = container_of(ptr, struct tomoyo_mount_acl, head);
if (!tomoyo_compare_number_union(flags, &acl->flags) ||
!tomoyo_compare_name_union(&rtype, &acl->fs_type) ||
!tomoyo_compare_name_union(&rdir, &acl->dir_name) ||
(need_dev &&
!tomoyo_compare_name_union(&rdev, &acl->dev_name)))
continue;
error = 0;
break;
}
if (error)
error = tomoyo_supervisor(r, TOMOYO_KEYWORD_ALLOW_MOUNT
"%s %s %s 0x%lX\n",
tomoyo_file_pattern(&rdev),
tomoyo_file_pattern(&rdir),
requested_type, flags);
do {
tomoyo_check_acl(r, tomoyo_check_mount_acl);
error = tomoyo_audit_mount_log(r);
} while (error == TOMOYO_RETRY_REQUEST);
out:
kfree(requested_dev_name);
kfree(requested_dir_name);