From 937bf6133b21b16965f75223085f4314ae32b8eb Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Wed, 2 Dec 2009 21:09:48 +0900 Subject: [PATCH] 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 Signed-off-by: James Morris --- security/tomoyo/common.c | 61 ++++++++++++---------------------------- security/tomoyo/common.h | 12 +++++--- security/tomoyo/file.c | 47 +++++++++++++++++++++++-------- security/tomoyo/tomoyo.c | 61 ++++++++++++++++++++++++++++++++++++++++ security/tomoyo/tomoyo.h | 12 ++++++-- 5 files changed, 132 insertions(+), 61 deletions(-) diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index e0d0354008b7..6c6061682438 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -842,52 +842,27 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain) if (ptr->type & TOMOYO_ACL_DELETED) continue; switch (tomoyo_acl_type2(ptr)) { - struct tomoyo_single_path_acl_record *acl1; - struct tomoyo_double_path_acl_record *acl2; - u16 perm; + struct tomoyo_single_path_acl_record *acl; + u32 perm; + u8 i; case TOMOYO_TYPE_SINGLE_PATH_ACL: - acl1 = container_of(ptr, - struct tomoyo_single_path_acl_record, - head); - perm = acl1->perm; - if (perm & (1 << TOMOYO_TYPE_EXECUTE_ACL)) - count++; - 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++; + acl = container_of(ptr, + struct tomoyo_single_path_acl_record, + head); + perm = acl->perm | (((u32) acl->perm_high) << 16); + for (i = 0; i < TOMOYO_MAX_SINGLE_PATH_OPERATION; i++) + if (perm & (1 << i)) + count++; + if (perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)) + count -= 2; break; case TOMOYO_TYPE_DOUBLE_PATH_ACL: - acl2 = container_of(ptr, + perm = container_of(ptr, struct tomoyo_double_path_acl_record, - head); - perm = acl2->perm; - if (perm & (1 << TOMOYO_TYPE_LINK_ACL)) - count++; - if (perm & (1 << TOMOYO_TYPE_RENAME_ACL)) - count++; + head)->perm; + for (i = 0; i < TOMOYO_MAX_DOUBLE_PATH_OPERATION; i++) + if (perm & (1 << i)) + count++; break; } } @@ -1426,7 +1401,7 @@ static bool tomoyo_print_single_path_acl(struct tomoyo_io_buffer *head, u8 bit; const char *atmark = ""; const char *filename; - const u16 perm = ptr->perm; + const u32 perm = ptr->perm | (((u32) ptr->perm_high) << 16); filename = ptr->filename->name; for (bit = head->read_bit; bit < TOMOYO_MAX_SINGLE_PATH_OPERATION; diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 92169d29b2db..bd10f9fa3511 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -108,7 +108,7 @@ struct tomoyo_path_info_with_data { * (b) type & 0x80 : whether the entry is marked as "deleted". * * 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" * without enlarging their structure size. */ @@ -184,10 +184,13 @@ struct tomoyo_domain_info { * Directives held by this structure are "allow_read/write", "allow_execute", * "allow_read", "allow_write", "allow_create", "allow_unlink", "allow_mkdir", * "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_acl_info head; /* type = TOMOYO_TYPE_SINGLE_PATH_ACL */ + u8 perm_high; u16 perm; /* Pointer to single pathname. */ 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 - * 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. * * (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. * (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_acl_info head; /* type = TOMOYO_TYPE_DOUBLE_PATH_ACL */ diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 5ae3a571559f..2d10f98fc551 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -81,12 +81,20 @@ static const char *tomoyo_sp_keyword[TOMOYO_MAX_SINGLE_PATH_OPERATION] = { [TOMOYO_TYPE_TRUNCATE_ACL] = "truncate", [TOMOYO_TYPE_SYMLINK_ACL] = "symlink", [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. */ static const char *tomoyo_dp_keyword[TOMOYO_MAX_DOUBLE_PATH_OPERATION] = { [TOMOYO_TYPE_LINK_ACL] = "link", [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, const struct tomoyo_path_info * filename, - const u16 perm, + const u32 perm, const bool may_use_pattern) { struct tomoyo_acl_info *ptr; @@ -668,8 +676,13 @@ static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info * continue; acl = container_of(ptr, struct tomoyo_single_path_acl_record, head); - if (!(acl->perm & perm)) - continue; + if (perm <= 0xFFFF) { + if (!(acl->perm & perm)) + continue; + } else { + if (!(acl->perm_high & (perm >> 16))) + continue; + } if (may_use_pattern || !acl->filename->is_patterned) { if (!tomoyo_path_matches_pattern(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 u8 operation) { - u16 perm = 0; + u32 perm = 0; if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) return 0; @@ -830,13 +843,13 @@ 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 = + static const u32 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; + const u32 perm = 1 << type; if (!domain) 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. */ if (ptr->type & TOMOYO_ACL_DELETED) acl->perm = 0; - acl->perm |= perm; + if (perm <= 0xFFFF) + acl->perm |= perm; + else + acl->perm_high |= (perm >> 16); 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)) @@ -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); if (!acl) goto out; - acl->perm = perm; + if (perm <= 0xFFFF) + acl->perm = perm; + else + acl->perm_high = (perm >> 16); if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL)) acl->perm |= rw_mask; acl->filename = saved_filename; @@ -887,12 +906,15 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, head); if (acl->filename != saved_filename) continue; - acl->perm &= ~perm; + if (perm <= 0xFFFF) + acl->perm &= ~perm; + else + acl->perm_high &= ~(perm >> 16); 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) + if (!acl->perm && !acl->perm_high) ptr->type |= TOMOYO_ACL_DELETED; error = 0; 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". * @operation: Type of operation. @@ -1217,6 +1239,7 @@ int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain, switch (operation) { case TOMOYO_TYPE_MKDIR_ACL: case TOMOYO_TYPE_RMDIR_ACL: + case TOMOYO_TYPE_CHROOT_ACL: if (!buf->is_dir) { /* * 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". * @operation: Type of operation. diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 9548a0984cc4..3fb5f6ea4fc9 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -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); } +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 * registering TOMOYO. @@ -295,6 +349,13 @@ static struct security_operations tomoyo_security_ops = { .path_mknod = tomoyo_path_mknod, .path_link = tomoyo_path_link, .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) diff --git a/security/tomoyo/tomoyo.h b/security/tomoyo/tomoyo.h index cd6ba0bf7069..fac02655ea4b 100644 --- a/security/tomoyo/tomoyo.h +++ b/security/tomoyo/tomoyo.h @@ -64,11 +64,19 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm); #define TOMOYO_TYPE_TRUNCATE_ACL 12 #define TOMOYO_TYPE_SYMLINK_ACL 13 #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_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_EXCEPTIONPOLICY 1 -- 2.39.5