TOMOYO: Add rest of file operation restrictions.

LSM hooks for chmod()/chown()/chroot() are now ready.
This patch utilizes these hooks.

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 2009-12-02 21:09:48 +09:00 committed by James Morris
parent 5d0901a3a0
commit 937bf6133b
5 changed files with 132 additions and 61 deletions

View File

@ -842,51 +842,26 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain)
if (ptr->type & TOMOYO_ACL_DELETED) if (ptr->type & TOMOYO_ACL_DELETED)
continue; continue;
switch (tomoyo_acl_type2(ptr)) { switch (tomoyo_acl_type2(ptr)) {
struct tomoyo_single_path_acl_record *acl1; struct tomoyo_single_path_acl_record *acl;
struct tomoyo_double_path_acl_record *acl2; u32 perm;
u16 perm; u8 i;
case TOMOYO_TYPE_SINGLE_PATH_ACL: case TOMOYO_TYPE_SINGLE_PATH_ACL:
acl1 = container_of(ptr, acl = container_of(ptr,
struct tomoyo_single_path_acl_record, struct tomoyo_single_path_acl_record,
head); head);
perm = acl1->perm; perm = acl->perm | (((u32) acl->perm_high) << 16);
if (perm & (1 << TOMOYO_TYPE_EXECUTE_ACL)) for (i = 0; i < TOMOYO_MAX_SINGLE_PATH_OPERATION; i++)
count++; if (perm & (1 << i))
if (perm &
((1 << TOMOYO_TYPE_READ_ACL) |
(1 << TOMOYO_TYPE_WRITE_ACL)))
count++;
if (perm & (1 << TOMOYO_TYPE_CREATE_ACL))
count++;
if (perm & (1 << TOMOYO_TYPE_UNLINK_ACL))
count++;
if (perm & (1 << TOMOYO_TYPE_MKDIR_ACL))
count++;
if (perm & (1 << TOMOYO_TYPE_RMDIR_ACL))
count++;
if (perm & (1 << TOMOYO_TYPE_MKFIFO_ACL))
count++;
if (perm & (1 << TOMOYO_TYPE_MKSOCK_ACL))
count++;
if (perm & (1 << TOMOYO_TYPE_MKBLOCK_ACL))
count++;
if (perm & (1 << TOMOYO_TYPE_MKCHAR_ACL))
count++;
if (perm & (1 << TOMOYO_TYPE_TRUNCATE_ACL))
count++;
if (perm & (1 << TOMOYO_TYPE_SYMLINK_ACL))
count++;
if (perm & (1 << TOMOYO_TYPE_REWRITE_ACL))
count++; count++;
if (perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))
count -= 2;
break; break;
case TOMOYO_TYPE_DOUBLE_PATH_ACL: case TOMOYO_TYPE_DOUBLE_PATH_ACL:
acl2 = container_of(ptr, perm = container_of(ptr,
struct tomoyo_double_path_acl_record, struct tomoyo_double_path_acl_record,
head); head)->perm;
perm = acl2->perm; for (i = 0; i < TOMOYO_MAX_DOUBLE_PATH_OPERATION; i++)
if (perm & (1 << TOMOYO_TYPE_LINK_ACL)) if (perm & (1 << i))
count++;
if (perm & (1 << TOMOYO_TYPE_RENAME_ACL))
count++; count++;
break; break;
} }
@ -1426,7 +1401,7 @@ static bool tomoyo_print_single_path_acl(struct tomoyo_io_buffer *head,
u8 bit; u8 bit;
const char *atmark = ""; const char *atmark = "";
const char *filename; const char *filename;
const u16 perm = ptr->perm; const u32 perm = ptr->perm | (((u32) ptr->perm_high) << 16);
filename = ptr->filename->name; filename = ptr->filename->name;
for (bit = head->read_bit; bit < TOMOYO_MAX_SINGLE_PATH_OPERATION; for (bit = head->read_bit; bit < TOMOYO_MAX_SINGLE_PATH_OPERATION;

View File

@ -108,7 +108,7 @@ struct tomoyo_path_info_with_data {
* (b) type & 0x80 : whether the entry is marked as "deleted". * (b) type & 0x80 : whether the entry is marked as "deleted".
* *
* Packing "struct tomoyo_acl_info" allows * Packing "struct tomoyo_acl_info" allows
* "struct tomoyo_single_path_acl_record" to embed "u16" and * "struct tomoyo_single_path_acl_record" to embed "u8" + "u16" and
* "struct tomoyo_double_path_acl_record" to embed "u8" * "struct tomoyo_double_path_acl_record" to embed "u8"
* without enlarging their structure size. * without enlarging their structure size.
*/ */
@ -184,10 +184,13 @@ struct tomoyo_domain_info {
* Directives held by this structure are "allow_read/write", "allow_execute", * Directives held by this structure are "allow_read/write", "allow_execute",
* "allow_read", "allow_write", "allow_create", "allow_unlink", "allow_mkdir", * "allow_read", "allow_write", "allow_create", "allow_unlink", "allow_mkdir",
* "allow_rmdir", "allow_mkfifo", "allow_mksock", "allow_mkblock", * "allow_rmdir", "allow_mkfifo", "allow_mksock", "allow_mkblock",
* "allow_mkchar", "allow_truncate", "allow_symlink" and "allow_rewrite". * "allow_mkchar", "allow_truncate", "allow_symlink", "allow_rewrite",
* "allow_chmod", "allow_chown", "allow_chgrp", "allow_chroot", "allow_mount"
* and "allow_unmount".
*/ */
struct tomoyo_single_path_acl_record { struct tomoyo_single_path_acl_record {
struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_SINGLE_PATH_ACL */ struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_SINGLE_PATH_ACL */
u8 perm_high;
u16 perm; u16 perm;
/* Pointer to single pathname. */ /* Pointer to single pathname. */
const struct tomoyo_path_info *filename; const struct tomoyo_path_info *filename;
@ -195,7 +198,7 @@ struct tomoyo_single_path_acl_record {
/* /*
* tomoyo_double_path_acl_record is a structure which is used for holding an * tomoyo_double_path_acl_record is a structure which is used for holding an
* entry with two pathnames operation (i.e. link() and rename()). * entry with two pathnames operation (i.e. link(), rename() and pivot_root()).
* It has following fields. * It has following fields.
* *
* (1) "head" which is a "struct tomoyo_acl_info". * (1) "head" which is a "struct tomoyo_acl_info".
@ -203,7 +206,8 @@ struct tomoyo_single_path_acl_record {
* (3) "filename1" is the source/old pathname. * (3) "filename1" is the source/old pathname.
* (4) "filename2" is the destination/new pathname. * (4) "filename2" is the destination/new pathname.
* *
* Directives held by this structure are "allow_rename" and "allow_link". * Directives held by this structure are "allow_rename", "allow_link" and
* "allow_pivot_root".
*/ */
struct tomoyo_double_path_acl_record { struct tomoyo_double_path_acl_record {
struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_DOUBLE_PATH_ACL */ struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_DOUBLE_PATH_ACL */

View File

@ -81,12 +81,20 @@ static const char *tomoyo_sp_keyword[TOMOYO_MAX_SINGLE_PATH_OPERATION] = {
[TOMOYO_TYPE_TRUNCATE_ACL] = "truncate", [TOMOYO_TYPE_TRUNCATE_ACL] = "truncate",
[TOMOYO_TYPE_SYMLINK_ACL] = "symlink", [TOMOYO_TYPE_SYMLINK_ACL] = "symlink",
[TOMOYO_TYPE_REWRITE_ACL] = "rewrite", [TOMOYO_TYPE_REWRITE_ACL] = "rewrite",
[TOMOYO_TYPE_IOCTL_ACL] = "ioctl",
[TOMOYO_TYPE_CHMOD_ACL] = "chmod",
[TOMOYO_TYPE_CHOWN_ACL] = "chown",
[TOMOYO_TYPE_CHGRP_ACL] = "chgrp",
[TOMOYO_TYPE_CHROOT_ACL] = "chroot",
[TOMOYO_TYPE_MOUNT_ACL] = "mount",
[TOMOYO_TYPE_UMOUNT_ACL] = "unmount",
}; };
/* Keyword array for double path operations. */ /* Keyword array for double path operations. */
static const char *tomoyo_dp_keyword[TOMOYO_MAX_DOUBLE_PATH_OPERATION] = { static const char *tomoyo_dp_keyword[TOMOYO_MAX_DOUBLE_PATH_OPERATION] = {
[TOMOYO_TYPE_LINK_ACL] = "link", [TOMOYO_TYPE_LINK_ACL] = "link",
[TOMOYO_TYPE_RENAME_ACL] = "rename", [TOMOYO_TYPE_RENAME_ACL] = "rename",
[TOMOYO_TYPE_PIVOT_ROOT_ACL] = "pivot_root",
}; };
/** /**
@ -655,7 +663,7 @@ static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info *
domain, domain,
const struct tomoyo_path_info * const struct tomoyo_path_info *
filename, filename,
const u16 perm, const u32 perm,
const bool may_use_pattern) const bool may_use_pattern)
{ {
struct tomoyo_acl_info *ptr; struct tomoyo_acl_info *ptr;
@ -668,8 +676,13 @@ static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info *
continue; continue;
acl = container_of(ptr, struct tomoyo_single_path_acl_record, acl = container_of(ptr, struct tomoyo_single_path_acl_record,
head); head);
if (perm <= 0xFFFF) {
if (!(acl->perm & perm)) if (!(acl->perm & perm))
continue; continue;
} else {
if (!(acl->perm_high & (perm >> 16)))
continue;
}
if (may_use_pattern || !acl->filename->is_patterned) { if (may_use_pattern || !acl->filename->is_patterned) {
if (!tomoyo_path_matches_pattern(filename, if (!tomoyo_path_matches_pattern(filename,
acl->filename)) acl->filename))
@ -697,7 +710,7 @@ static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain,
const struct tomoyo_path_info *filename, const struct tomoyo_path_info *filename,
const u8 operation) const u8 operation)
{ {
u16 perm = 0; u32 perm = 0;
if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
return 0; return 0;
@ -830,13 +843,13 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
struct tomoyo_domain_info * struct tomoyo_domain_info *
const domain, const bool is_delete) const domain, const bool is_delete)
{ {
static const u16 rw_mask = static const u32 rw_mask =
(1 << TOMOYO_TYPE_READ_ACL) | (1 << TOMOYO_TYPE_WRITE_ACL); (1 << TOMOYO_TYPE_READ_ACL) | (1 << TOMOYO_TYPE_WRITE_ACL);
const struct tomoyo_path_info *saved_filename; const struct tomoyo_path_info *saved_filename;
struct tomoyo_acl_info *ptr; struct tomoyo_acl_info *ptr;
struct tomoyo_single_path_acl_record *acl; struct tomoyo_single_path_acl_record *acl;
int error = -ENOMEM; int error = -ENOMEM;
const u16 perm = 1 << type; const u32 perm = 1 << type;
if (!domain) if (!domain)
return -EINVAL; return -EINVAL;
@ -858,7 +871,10 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
/* Special case. Clear all bits if marked as deleted. */ /* Special case. Clear all bits if marked as deleted. */
if (ptr->type & TOMOYO_ACL_DELETED) if (ptr->type & TOMOYO_ACL_DELETED)
acl->perm = 0; acl->perm = 0;
if (perm <= 0xFFFF)
acl->perm |= perm; acl->perm |= perm;
else
acl->perm_high |= (perm >> 16);
if ((acl->perm & rw_mask) == rw_mask) if ((acl->perm & rw_mask) == rw_mask)
acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL; acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL;
else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)) else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))
@ -871,7 +887,10 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_SINGLE_PATH_ACL); acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_SINGLE_PATH_ACL);
if (!acl) if (!acl)
goto out; goto out;
if (perm <= 0xFFFF)
acl->perm = perm; acl->perm = perm;
else
acl->perm_high = (perm >> 16);
if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL)) if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL))
acl->perm |= rw_mask; acl->perm |= rw_mask;
acl->filename = saved_filename; acl->filename = saved_filename;
@ -887,12 +906,15 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
head); head);
if (acl->filename != saved_filename) if (acl->filename != saved_filename)
continue; continue;
if (perm <= 0xFFFF)
acl->perm &= ~perm; acl->perm &= ~perm;
else
acl->perm_high &= ~(perm >> 16);
if ((acl->perm & rw_mask) != rw_mask) if ((acl->perm & rw_mask) != rw_mask)
acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL); acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL);
else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))) else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)))
acl->perm &= ~rw_mask; acl->perm &= ~rw_mask;
if (!acl->perm) if (!acl->perm && !acl->perm_high)
ptr->type |= TOMOYO_ACL_DELETED; ptr->type |= TOMOYO_ACL_DELETED;
error = 0; error = 0;
break; break;
@ -1193,7 +1215,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
} }
/** /**
* tomoyo_check_1path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate" and "symlink". * tomoyo_check_1path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate", "symlink", "ioctl", "chmod", "chown", "chgrp", "chroot", "mount" and "unmount".
* *
* @domain: Pointer to "struct tomoyo_domain_info". * @domain: Pointer to "struct tomoyo_domain_info".
* @operation: Type of operation. * @operation: Type of operation.
@ -1217,6 +1239,7 @@ int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain,
switch (operation) { switch (operation) {
case TOMOYO_TYPE_MKDIR_ACL: case TOMOYO_TYPE_MKDIR_ACL:
case TOMOYO_TYPE_RMDIR_ACL: case TOMOYO_TYPE_RMDIR_ACL:
case TOMOYO_TYPE_CHROOT_ACL:
if (!buf->is_dir) { if (!buf->is_dir) {
/* /*
* tomoyo_get_path() reserves space for appending "/." * tomoyo_get_path() reserves space for appending "/."
@ -1270,7 +1293,7 @@ int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain,
} }
/** /**
* tomoyo_check_2path_perm - Check permission for "rename" and "link". * tomoyo_check_2path_perm - Check permission for "rename", "link" and "pivot_root".
* *
* @domain: Pointer to "struct tomoyo_domain_info". * @domain: Pointer to "struct tomoyo_domain_info".
* @operation: Type of operation. * @operation: Type of operation.

View File

@ -271,6 +271,60 @@ static int tomoyo_dentry_open(struct file *f, const struct cred *cred)
return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, flags); return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, flags);
} }
static int tomoyo_file_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
return tomoyo_check_1path_perm(tomoyo_domain(), TOMOYO_TYPE_IOCTL_ACL,
&file->f_path);
}
static int tomoyo_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
mode_t mode)
{
struct path path = { mnt, dentry };
return tomoyo_check_1path_perm(tomoyo_domain(), TOMOYO_TYPE_CHMOD_ACL,
&path);
}
static int tomoyo_path_chown(struct path *path, uid_t uid, gid_t gid)
{
int error = 0;
if (uid != (uid_t) -1)
error = tomoyo_check_1path_perm(tomoyo_domain(),
TOMOYO_TYPE_CHOWN_ACL, path);
if (!error && gid != (gid_t) -1)
error = tomoyo_check_1path_perm(tomoyo_domain(),
TOMOYO_TYPE_CHGRP_ACL, path);
return error;
}
static int tomoyo_path_chroot(struct path *path)
{
return tomoyo_check_1path_perm(tomoyo_domain(), TOMOYO_TYPE_CHROOT_ACL,
path);
}
static int tomoyo_sb_mount(char *dev_name, struct path *path,
char *type, unsigned long flags, void *data)
{
return tomoyo_check_1path_perm(tomoyo_domain(), TOMOYO_TYPE_MOUNT_ACL,
path);
}
static int tomoyo_sb_umount(struct vfsmount *mnt, int flags)
{
struct path path = { mnt, mnt->mnt_root };
return tomoyo_check_1path_perm(tomoyo_domain(), TOMOYO_TYPE_UMOUNT_ACL,
&path);
}
static int tomoyo_sb_pivotroot(struct path *old_path, struct path *new_path)
{
return tomoyo_check_2path_perm(tomoyo_domain(),
TOMOYO_TYPE_PIVOT_ROOT_ACL,
new_path, old_path);
}
/* /*
* tomoyo_security_ops is a "struct security_operations" which is used for * tomoyo_security_ops is a "struct security_operations" which is used for
* registering TOMOYO. * registering TOMOYO.
@ -295,6 +349,13 @@ static struct security_operations tomoyo_security_ops = {
.path_mknod = tomoyo_path_mknod, .path_mknod = tomoyo_path_mknod,
.path_link = tomoyo_path_link, .path_link = tomoyo_path_link,
.path_rename = tomoyo_path_rename, .path_rename = tomoyo_path_rename,
.file_ioctl = tomoyo_file_ioctl,
.path_chmod = tomoyo_path_chmod,
.path_chown = tomoyo_path_chown,
.path_chroot = tomoyo_path_chroot,
.sb_mount = tomoyo_sb_mount,
.sb_umount = tomoyo_sb_umount,
.sb_pivotroot = tomoyo_sb_pivotroot,
}; };
static int __init tomoyo_init(void) static int __init tomoyo_init(void)

View File

@ -64,11 +64,19 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm);
#define TOMOYO_TYPE_TRUNCATE_ACL 12 #define TOMOYO_TYPE_TRUNCATE_ACL 12
#define TOMOYO_TYPE_SYMLINK_ACL 13 #define TOMOYO_TYPE_SYMLINK_ACL 13
#define TOMOYO_TYPE_REWRITE_ACL 14 #define TOMOYO_TYPE_REWRITE_ACL 14
#define TOMOYO_MAX_SINGLE_PATH_OPERATION 15 #define TOMOYO_TYPE_IOCTL_ACL 15
#define TOMOYO_TYPE_CHMOD_ACL 16
#define TOMOYO_TYPE_CHOWN_ACL 17
#define TOMOYO_TYPE_CHGRP_ACL 18
#define TOMOYO_TYPE_CHROOT_ACL 19
#define TOMOYO_TYPE_MOUNT_ACL 20
#define TOMOYO_TYPE_UMOUNT_ACL 21
#define TOMOYO_MAX_SINGLE_PATH_OPERATION 22
#define TOMOYO_TYPE_LINK_ACL 0 #define TOMOYO_TYPE_LINK_ACL 0
#define TOMOYO_TYPE_RENAME_ACL 1 #define TOMOYO_TYPE_RENAME_ACL 1
#define TOMOYO_MAX_DOUBLE_PATH_OPERATION 2 #define TOMOYO_TYPE_PIVOT_ROOT_ACL 2
#define TOMOYO_MAX_DOUBLE_PATH_OPERATION 3
#define TOMOYO_DOMAINPOLICY 0 #define TOMOYO_DOMAINPOLICY 0
#define TOMOYO_EXCEPTIONPOLICY 1 #define TOMOYO_EXCEPTIONPOLICY 1