From 937bf6133b21b16965f75223085f4314ae32b8eb Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Wed, 2 Dec 2009 21:09:48 +0900 Subject: 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(-) (limited to 'security/tomoyo') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index e0d0354..6c60616 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 92169d2..bd10f9f 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 5ae3a57..2d10f98 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 9548a09..3fb5f6e 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 cd6ba0b..fac0265 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 -- cgit v1.1 From 67fa4880c5e059428392ca6f7c2f9c38e8546fea Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Wed, 9 Dec 2009 15:36:04 +0900 Subject: TOMOYO: Compare filesystem by magic number rather than by name. Please apply below one after merging 1557d33007f63dd96e5d15f33af389378e5f2e54 (Merge git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/sysctl-2.6). ---------- [PATCH for 2.6.33] TOMOYO: Compare filesystem by magic number rather than by name. We can use magic number for checking whether the filesystem is procfs or not. Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/realpath.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'security/tomoyo') diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 18369d49..e3c7aa0 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "common.h" #include "realpath.h" @@ -112,7 +113,7 @@ int tomoyo_realpath_from_path2(struct path *path, char *newname, path_put(&ns_root); /* Prepend "/proc" prefix if using internal proc vfs mount. */ if (!IS_ERR(sp) && (path->mnt->mnt_parent == path->mnt) && - (strcmp(path->mnt->mnt_sb->s_type->name, "proc") == 0)) { + (path->mnt->mnt_sb->s_magic == PROC_SUPER_MAGIC)) { sp -= 5; if (sp >= newname) memcpy(sp, "/proc", 5); -- cgit v1.1 From fdb8ebb729bbb640e64028a4f579a02ebc405727 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Tue, 8 Dec 2009 09:34:43 +0900 Subject: TOMOYO: Use RCU primitives for list operation Replace list operation with RCU primitives and replace down_read()/up_read() with srcu_read_lock()/srcu_read_unlock(). Signed-off-by: Tetsuo Handa Acked-by: Serge Hallyn Signed-off-by: James Morris --- security/tomoyo/common.c | 90 ++++++++++++++++++++----------------- security/tomoyo/common.h | 28 +++++++++--- security/tomoyo/domain.c | 63 +++++++++++++++----------- security/tomoyo/file.c | 110 +++++++++++++++++++++++++++++++-------------- security/tomoyo/realpath.c | 8 ++-- security/tomoyo/tomoyo.c | 20 +++++++-- 6 files changed, 207 insertions(+), 112 deletions(-) (limited to 'security/tomoyo') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 6c60616..f01b936 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -365,10 +365,9 @@ bool tomoyo_is_domain_def(const unsigned char *buffer) * * @domainname: The domainname to find. * - * Caller must call down_read(&tomoyo_domain_list_lock); or - * down_write(&tomoyo_domain_list_lock); . - * * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise. + * + * Caller holds tomoyo_read_lock(). */ struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname) { @@ -377,7 +376,7 @@ struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname) name.name = domainname; tomoyo_fill_path_info(&name); - list_for_each_entry(domain, &tomoyo_domain_list, list) { + list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { if (!domain->is_deleted && !tomoyo_pathcmp(&name, domain->domainname)) return domain; @@ -829,6 +828,8 @@ bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain) * @domain: Pointer to "struct tomoyo_domain_info". * * Returns true if the domain is not exceeded quota, false otherwise. + * + * Caller holds tomoyo_read_lock(). */ bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain) { @@ -837,8 +838,7 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain) if (!domain) return true; - down_read(&tomoyo_domain_acl_info_list_lock); - list_for_each_entry(ptr, &domain->acl_info_list, list) { + list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { if (ptr->type & TOMOYO_ACL_DELETED) continue; switch (tomoyo_acl_type2(ptr)) { @@ -866,7 +866,6 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain) break; } } - up_read(&tomoyo_domain_acl_info_list_lock); if (count < tomoyo_check_flags(domain, TOMOYO_MAX_ACCEPT_ENTRY)) return true; if (!domain->quota_warned) { @@ -1096,6 +1095,8 @@ static DECLARE_RWSEM(tomoyo_policy_manager_list_lock); * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_update_manager_entry(const char *manager, const bool is_delete) @@ -1118,7 +1119,7 @@ static int tomoyo_update_manager_entry(const char *manager, if (!saved_manager) return -ENOMEM; down_write(&tomoyo_policy_manager_list_lock); - list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) { + list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { if (ptr->manager != saved_manager) continue; ptr->is_deleted = is_delete; @@ -1134,7 +1135,7 @@ static int tomoyo_update_manager_entry(const char *manager, goto out; new_entry->manager = saved_manager; new_entry->is_domain = is_domain; - list_add_tail(&new_entry->list, &tomoyo_policy_manager_list); + list_add_tail_rcu(&new_entry->list, &tomoyo_policy_manager_list); error = 0; out: up_write(&tomoyo_policy_manager_list_lock); @@ -1147,6 +1148,8 @@ static int tomoyo_update_manager_entry(const char *manager, * @head: Pointer to "struct tomoyo_io_buffer". * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head) { @@ -1166,6 +1169,8 @@ static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head) * @head: Pointer to "struct tomoyo_io_buffer". * * Returns 0. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head) { @@ -1174,7 +1179,6 @@ static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head) if (head->read_eof) return 0; - down_read(&tomoyo_policy_manager_list_lock); list_for_each_cookie(pos, head->read_var2, &tomoyo_policy_manager_list) { struct tomoyo_policy_manager_entry *ptr; @@ -1186,7 +1190,6 @@ static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head) if (!done) break; } - up_read(&tomoyo_policy_manager_list_lock); head->read_eof = done; return 0; } @@ -1196,6 +1199,8 @@ static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head) * * Returns true if the current process is permitted to modify policy * via /sys/kernel/security/tomoyo/ interface. + * + * Caller holds tomoyo_read_lock(). */ static bool tomoyo_is_policy_manager(void) { @@ -1209,29 +1214,25 @@ static bool tomoyo_is_policy_manager(void) return true; if (!tomoyo_manage_by_non_root && (task->cred->uid || task->cred->euid)) return false; - down_read(&tomoyo_policy_manager_list_lock); - list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) { + list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { if (!ptr->is_deleted && ptr->is_domain && !tomoyo_pathcmp(domainname, ptr->manager)) { found = true; break; } } - up_read(&tomoyo_policy_manager_list_lock); if (found) return true; exe = tomoyo_get_exe(); if (!exe) return false; - down_read(&tomoyo_policy_manager_list_lock); - list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) { + list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { if (!ptr->is_deleted && !ptr->is_domain && !strcmp(exe, ptr->manager->name)) { found = true; break; } } - up_read(&tomoyo_policy_manager_list_lock); if (!found) { /* Reduce error messages. */ static pid_t last_pid; const pid_t pid = current->pid; @@ -1252,6 +1253,8 @@ static bool tomoyo_is_policy_manager(void) * @data: String to parse. * * Returns true on success, false otherwise. + * + * Caller holds tomoyo_read_lock(). */ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head, const char *data) @@ -1267,11 +1270,8 @@ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head, domain = tomoyo_real_domain(p); read_unlock(&tasklist_lock); } else if (!strncmp(data, "domain=", 7)) { - if (tomoyo_is_domain_def(data + 7)) { - down_read(&tomoyo_domain_list_lock); + if (tomoyo_is_domain_def(data + 7)) domain = tomoyo_find_domain(data + 7); - up_read(&tomoyo_domain_list_lock); - } } else return false; head->write_var1 = domain; @@ -1285,13 +1285,11 @@ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head, if (domain) { struct tomoyo_domain_info *d; head->read_var1 = NULL; - down_read(&tomoyo_domain_list_lock); - list_for_each_entry(d, &tomoyo_domain_list, list) { + list_for_each_entry_rcu(d, &tomoyo_domain_list, list) { if (d == domain) break; head->read_var1 = &d->list; } - up_read(&tomoyo_domain_list_lock); head->read_var2 = NULL; head->read_bit = 0; head->read_step = 0; @@ -1307,6 +1305,8 @@ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head, * @domainname: The name of domain. * * Returns 0. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_delete_domain(char *domainname) { @@ -1317,7 +1317,7 @@ static int tomoyo_delete_domain(char *domainname) tomoyo_fill_path_info(&name); down_write(&tomoyo_domain_list_lock); /* Is there an active domain? */ - list_for_each_entry(domain, &tomoyo_domain_list, list) { + list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { /* Never delete tomoyo_kernel_domain */ if (domain == &tomoyo_kernel_domain) continue; @@ -1337,6 +1337,8 @@ static int tomoyo_delete_domain(char *domainname) * @head: Pointer to "struct tomoyo_io_buffer". * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head) { @@ -1359,11 +1361,9 @@ static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head) domain = NULL; if (is_delete) tomoyo_delete_domain(data); - else if (is_select) { - down_read(&tomoyo_domain_list_lock); + else if (is_select) domain = tomoyo_find_domain(data); - up_read(&tomoyo_domain_list_lock); - } else + else domain = tomoyo_find_or_assign_new_domain(data, 0); head->write_var1 = domain; return 0; @@ -1508,6 +1508,8 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, * @head: Pointer to "struct tomoyo_io_buffer". * * Returns 0. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head) { @@ -1519,7 +1521,6 @@ static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head) return 0; if (head->read_step == 0) head->read_step = 1; - down_read(&tomoyo_domain_list_lock); list_for_each_cookie(dpos, head->read_var1, &tomoyo_domain_list) { struct tomoyo_domain_info *domain; const char *quota_exceeded = ""; @@ -1552,7 +1553,6 @@ acl_loop: if (head->read_step == 3) goto tail_mark; /* Print ACL entries in the domain. */ - down_read(&tomoyo_domain_acl_info_list_lock); list_for_each_cookie(apos, head->read_var2, &domain->acl_info_list) { struct tomoyo_acl_info *ptr @@ -1562,7 +1562,6 @@ acl_loop: if (!done) break; } - up_read(&tomoyo_domain_acl_info_list_lock); if (!done) break; head->read_step = 3; @@ -1574,7 +1573,6 @@ tail_mark: if (head->read_single_domain) break; } - up_read(&tomoyo_domain_list_lock); head->read_eof = done; return 0; } @@ -1590,6 +1588,8 @@ tail_mark: * * ( echo "select " $domainname; echo "use_profile " $profile ) | * /usr/lib/ccs/loadpolicy -d + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head) { @@ -1601,9 +1601,7 @@ static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head) if (!cp) return -EINVAL; *cp = '\0'; - down_read(&tomoyo_domain_list_lock); domain = tomoyo_find_domain(cp + 1); - up_read(&tomoyo_domain_list_lock); if (strict_strtoul(data, 10, &profile)) return -EINVAL; if (domain && profile < TOMOYO_MAX_PROFILES @@ -1625,6 +1623,8 @@ static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head) * awk ' { if ( domainname == "" ) { if ( $1 == "" ) * domainname = $0; } else if ( $1 == "use_profile" ) { * print $2 " " domainname; domainname = ""; } } ; ' + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head) { @@ -1633,7 +1633,6 @@ static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head) if (head->read_eof) return 0; - down_read(&tomoyo_domain_list_lock); list_for_each_cookie(pos, head->read_var1, &tomoyo_domain_list) { struct tomoyo_domain_info *domain; domain = list_entry(pos, struct tomoyo_domain_info, list); @@ -1644,7 +1643,6 @@ static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head) if (!done) break; } - up_read(&tomoyo_domain_list_lock); head->read_eof = done; return 0; } @@ -1701,6 +1699,8 @@ static int tomoyo_read_pid(struct tomoyo_io_buffer *head) * @head: Pointer to "struct tomoyo_io_buffer". * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head) { @@ -1735,6 +1735,8 @@ static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head) * @head: Pointer to "struct tomoyo_io_buffer". * * Returns 0 on success, -EINVAL otherwise. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_read_exception_policy(struct tomoyo_io_buffer *head) { @@ -1864,15 +1866,13 @@ void tomoyo_load_policy(const char *filename) tomoyo_policy_loaded = true; { /* Check all profiles currently assigned to domains are defined. */ struct tomoyo_domain_info *domain; - down_read(&tomoyo_domain_list_lock); - list_for_each_entry(domain, &tomoyo_domain_list, list) { + list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { const u8 profile = domain->profile; if (tomoyo_profile_ptr[profile]) continue; panic("Profile %u (used by '%s') not defined.\n", profile, domain->domainname->name); } - up_read(&tomoyo_domain_list_lock); } } @@ -1920,6 +1920,8 @@ static int tomoyo_read_self_domain(struct tomoyo_io_buffer *head) * @file: Pointer to "struct file". * * Associates policy handler and returns 0 on success, -ENOMEM otherwise. + * + * Caller acquires tomoyo_read_lock(). */ static int tomoyo_open_control(const u8 type, struct file *file) { @@ -2005,6 +2007,7 @@ static int tomoyo_open_control(const u8 type, struct file *file) return -ENOMEM; } } + head->reader_idx = tomoyo_read_lock(); file->private_data = head; /* * Call the handler now if the file is @@ -2026,6 +2029,8 @@ static int tomoyo_open_control(const u8 type, struct file *file) * @buffer_len: Size of @buffer. * * Returns bytes read on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_read_control(struct file *file, char __user *buffer, const int buffer_len) @@ -2069,6 +2074,8 @@ static int tomoyo_read_control(struct file *file, char __user *buffer, * @buffer_len: Size of @buffer. * * Returns @buffer_len on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_write_control(struct file *file, const char __user *buffer, const int buffer_len) @@ -2119,11 +2126,14 @@ static int tomoyo_write_control(struct file *file, const char __user *buffer, * @file: Pointer to "struct file". * * Releases memory and returns 0. + * + * Caller looses tomoyo_read_lock(). */ static int tomoyo_close_control(struct file *file) { struct tomoyo_io_buffer *head = file->private_data; + tomoyo_read_unlock(head->reader_idx); /* Release memory used for policy I/O. */ tomoyo_free(head->read_buf); head->read_buf = NULL; diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index bd10f9f..c6f1392 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -269,6 +269,8 @@ struct tomoyo_io_buffer { int (*write) (struct tomoyo_io_buffer *); /* Exclusive lock for this structure. */ struct mutex io_sem; + /* Index returned by tomoyo_read_lock(). */ + int reader_idx; /* The position currently reading from. */ struct list_head *read_var1; /* Extra variables for reading. */ @@ -446,16 +448,28 @@ extern struct tomoyo_domain_info tomoyo_kernel_domain; * @cookie: the &struct list_head to use as a cookie. * @head: the head for your list. * - * Same with list_for_each() except that this primitive uses @cookie + * Same with list_for_each_rcu() except that this primitive uses @cookie * so that we can continue iteration. * @cookie must be NULL when iteration starts, and @cookie will become * NULL when iteration finishes. */ -#define list_for_each_cookie(pos, cookie, head) \ - for (({ if (!cookie) \ - cookie = head; }), \ - pos = (cookie)->next; \ - prefetch(pos->next), pos != (head) || ((cookie) = NULL); \ - (cookie) = pos, pos = pos->next) +#define list_for_each_cookie(pos, cookie, head) \ + for (({ if (!cookie) \ + cookie = head; }), \ + pos = rcu_dereference((cookie)->next); \ + prefetch(pos->next), pos != (head) || ((cookie) = NULL); \ + (cookie) = pos, pos = rcu_dereference(pos->next)) + +extern struct srcu_struct tomoyo_ss; + +static inline int tomoyo_read_lock(void) +{ + return srcu_read_lock(&tomoyo_ss); +} + +static inline void tomoyo_read_unlock(int idx) +{ + srcu_read_unlock(&tomoyo_ss, idx); +} #endif /* !defined(_SECURITY_TOMOYO_COMMON_H) */ diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index fcf52ac..2fd1901 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -217,6 +217,8 @@ static DECLARE_RWSEM(tomoyo_domain_initializer_list_lock); * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_update_domain_initializer_entry(const char *domainname, const char *program, @@ -246,7 +248,7 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, if (!saved_program) return -ENOMEM; down_write(&tomoyo_domain_initializer_list_lock); - list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) { + list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { if (ptr->is_not != is_not || ptr->domainname != saved_domainname || ptr->program != saved_program) @@ -266,7 +268,7 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, new_entry->program = saved_program; new_entry->is_not = is_not; new_entry->is_last_name = is_last_name; - list_add_tail(&new_entry->list, &tomoyo_domain_initializer_list); + list_add_tail_rcu(&new_entry->list, &tomoyo_domain_initializer_list); error = 0; out: up_write(&tomoyo_domain_initializer_list_lock); @@ -279,13 +281,14 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, * @head: Pointer to "struct tomoyo_io_buffer". * * Returns true on success, false otherwise. + * + * Caller holds tomoyo_read_lock(). */ bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) { struct list_head *pos; bool done = true; - down_read(&tomoyo_domain_initializer_list_lock); list_for_each_cookie(pos, head->read_var2, &tomoyo_domain_initializer_list) { const char *no; @@ -308,7 +311,6 @@ bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) if (!done) break; } - up_read(&tomoyo_domain_initializer_list_lock); return done; } @@ -320,6 +322,8 @@ bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, const bool is_delete) @@ -345,6 +349,8 @@ int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, * * Returns true if executing @program reinitializes domain transition, * false otherwise. + * + * Caller holds tomoyo_read_lock(). */ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * domainname, @@ -355,8 +361,7 @@ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * struct tomoyo_domain_initializer_entry *ptr; bool flag = false; - down_read(&tomoyo_domain_initializer_list_lock); - list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) { + list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { if (ptr->is_deleted) continue; if (ptr->domainname) { @@ -376,7 +381,6 @@ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * } flag = true; } - up_read(&tomoyo_domain_initializer_list_lock); return flag; } @@ -430,6 +434,8 @@ static DECLARE_RWSEM(tomoyo_domain_keeper_list_lock); * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_update_domain_keeper_entry(const char *domainname, const char *program, @@ -459,7 +465,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, if (!saved_domainname) return -ENOMEM; down_write(&tomoyo_domain_keeper_list_lock); - list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) { + list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { if (ptr->is_not != is_not || ptr->domainname != saved_domainname || ptr->program != saved_program) @@ -479,7 +485,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, new_entry->program = saved_program; new_entry->is_not = is_not; new_entry->is_last_name = is_last_name; - list_add_tail(&new_entry->list, &tomoyo_domain_keeper_list); + list_add_tail_rcu(&new_entry->list, &tomoyo_domain_keeper_list); error = 0; out: up_write(&tomoyo_domain_keeper_list_lock); @@ -493,6 +499,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, * @is_not: True if it is "no_keep_domain" entry. * @is_delete: True if it is a delete request. * + * Caller holds tomoyo_read_lock(). */ int tomoyo_write_domain_keeper_policy(char *data, const bool is_not, const bool is_delete) @@ -513,13 +520,14 @@ int tomoyo_write_domain_keeper_policy(char *data, const bool is_not, * @head: Pointer to "struct tomoyo_io_buffer". * * Returns true on success, false otherwise. + * + * Caller holds tomoyo_read_lock(). */ bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) { struct list_head *pos; bool done = true; - down_read(&tomoyo_domain_keeper_list_lock); list_for_each_cookie(pos, head->read_var2, &tomoyo_domain_keeper_list) { struct tomoyo_domain_keeper_entry *ptr; @@ -542,7 +550,6 @@ bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) if (!done) break; } - up_read(&tomoyo_domain_keeper_list_lock); return done; } @@ -555,6 +562,8 @@ bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) * * Returns true if executing @program supresses domain transition, * false otherwise. + * + * Caller holds tomoyo_read_lock(). */ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, const struct tomoyo_path_info *program, @@ -563,8 +572,7 @@ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, struct tomoyo_domain_keeper_entry *ptr; bool flag = false; - down_read(&tomoyo_domain_keeper_list_lock); - list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) { + list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { if (ptr->is_deleted) continue; if (!ptr->is_last_name) { @@ -582,7 +590,6 @@ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, } flag = true; } - up_read(&tomoyo_domain_keeper_list_lock); return flag; } @@ -627,6 +634,8 @@ static DECLARE_RWSEM(tomoyo_alias_list_lock); * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_update_alias_entry(const char *original_name, const char *aliased_name, @@ -646,7 +655,7 @@ static int tomoyo_update_alias_entry(const char *original_name, if (!saved_original_name || !saved_aliased_name) return -ENOMEM; down_write(&tomoyo_alias_list_lock); - list_for_each_entry(ptr, &tomoyo_alias_list, list) { + list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { if (ptr->original_name != saved_original_name || ptr->aliased_name != saved_aliased_name) continue; @@ -663,7 +672,7 @@ static int tomoyo_update_alias_entry(const char *original_name, goto out; new_entry->original_name = saved_original_name; new_entry->aliased_name = saved_aliased_name; - list_add_tail(&new_entry->list, &tomoyo_alias_list); + list_add_tail_rcu(&new_entry->list, &tomoyo_alias_list); error = 0; out: up_write(&tomoyo_alias_list_lock); @@ -676,13 +685,14 @@ static int tomoyo_update_alias_entry(const char *original_name, * @head: Pointer to "struct tomoyo_io_buffer". * * Returns true on success, false otherwise. + * + * Caller holds tomoyo_read_lock(). */ bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) { struct list_head *pos; bool done = true; - down_read(&tomoyo_alias_list_lock); list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) { struct tomoyo_alias_entry *ptr; @@ -695,7 +705,6 @@ bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) if (!done) break; } - up_read(&tomoyo_alias_list_lock); return done; } @@ -706,6 +715,8 @@ bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ int tomoyo_write_alias_policy(char *data, const bool is_delete) { @@ -724,6 +735,8 @@ int tomoyo_write_alias_policy(char *data, const bool is_delete) * @profile: Profile number to assign if the domain was newly created. * * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise. + * + * Caller holds tomoyo_read_lock(). */ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * domainname, @@ -742,7 +755,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * if (!saved_domainname) goto out; /* Can I reuse memory of deleted domain? */ - list_for_each_entry(domain, &tomoyo_domain_list, list) { + list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { struct task_struct *p; struct tomoyo_acl_info *ptr; bool flag; @@ -760,7 +773,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * read_unlock(&tasklist_lock); if (flag) continue; - list_for_each_entry(ptr, &domain->acl_info_list, list) { + list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { ptr->type |= TOMOYO_ACL_DELETED; } tomoyo_set_domain_flag(domain, true, domain->flags); @@ -776,7 +789,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * INIT_LIST_HEAD(&domain->acl_info_list); domain->domainname = saved_domainname; domain->profile = profile; - list_add_tail(&domain->list, &tomoyo_domain_list); + list_add_tail_rcu(&domain->list, &tomoyo_domain_list); } out: up_write(&tomoyo_domain_list_lock); @@ -789,6 +802,8 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * * @bprm: Pointer to "struct linux_binprm". * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ int tomoyo_find_next_domain(struct linux_binprm *bprm) { @@ -849,8 +864,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) if (tomoyo_pathcmp(&r, &s)) { struct tomoyo_alias_entry *ptr; /* Is this program allowed to be called via symbolic links? */ - down_read(&tomoyo_alias_list_lock); - list_for_each_entry(ptr, &tomoyo_alias_list, list) { + list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { if (ptr->is_deleted || tomoyo_pathcmp(&r, ptr->original_name) || tomoyo_pathcmp(&s, ptr->aliased_name)) @@ -861,7 +875,6 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) tomoyo_fill_path_info(&r); break; } - up_read(&tomoyo_alias_list_lock); } /* Check execute permission. */ @@ -892,9 +905,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) } if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN) goto done; - down_read(&tomoyo_domain_list_lock); domain = tomoyo_find_domain(new_domain_name); - up_read(&tomoyo_domain_list_lock); if (domain) goto done; if (is_enforce) diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 482f0e7..3c47286 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -213,6 +213,8 @@ static DECLARE_RWSEM(tomoyo_globally_readable_list_lock); * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_update_globally_readable_entry(const char *filename, const bool is_delete) @@ -228,7 +230,7 @@ static int tomoyo_update_globally_readable_entry(const char *filename, if (!saved_filename) return -ENOMEM; down_write(&tomoyo_globally_readable_list_lock); - list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) { + list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { if (ptr->filename != saved_filename) continue; ptr->is_deleted = is_delete; @@ -243,7 +245,7 @@ static int tomoyo_update_globally_readable_entry(const char *filename, if (!new_entry) goto out; new_entry->filename = saved_filename; - list_add_tail(&new_entry->list, &tomoyo_globally_readable_list); + list_add_tail_rcu(&new_entry->list, &tomoyo_globally_readable_list); error = 0; out: up_write(&tomoyo_globally_readable_list_lock); @@ -256,21 +258,22 @@ static int tomoyo_update_globally_readable_entry(const char *filename, * @filename: The filename to check. * * Returns true if any domain can open @filename for reading, false otherwise. + * + * Caller holds tomoyo_read_lock(). */ 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) { + + list_for_each_entry_rcu(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; } @@ -281,6 +284,8 @@ static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info * * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ int tomoyo_write_globally_readable_policy(char *data, const bool is_delete) { @@ -293,13 +298,14 @@ int tomoyo_write_globally_readable_policy(char *data, const bool is_delete) * @head: Pointer to "struct tomoyo_io_buffer". * * Returns true on success, false otherwise. + * + * Caller holds tomoyo_read_lock(). */ 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; @@ -313,7 +319,6 @@ bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head) if (!done) break; } - up_read(&tomoyo_globally_readable_list_lock); return done; } @@ -356,6 +361,8 @@ static DECLARE_RWSEM(tomoyo_pattern_list_lock); * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_update_file_pattern_entry(const char *pattern, const bool is_delete) @@ -371,7 +378,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, if (!saved_pattern) return -ENOMEM; down_write(&tomoyo_pattern_list_lock); - list_for_each_entry(ptr, &tomoyo_pattern_list, list) { + list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { if (saved_pattern != ptr->pattern) continue; ptr->is_deleted = is_delete; @@ -386,7 +393,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, if (!new_entry) goto out; new_entry->pattern = saved_pattern; - list_add_tail(&new_entry->list, &tomoyo_pattern_list); + list_add_tail_rcu(&new_entry->list, &tomoyo_pattern_list); error = 0; out: up_write(&tomoyo_pattern_list_lock); @@ -399,6 +406,8 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, * @filename: The filename to find patterned pathname. * * Returns pointer to pathname pattern if matched, @filename otherwise. + * + * Caller holds tomoyo_read_lock(). */ static const struct tomoyo_path_info * tomoyo_get_file_pattern(const struct tomoyo_path_info *filename) @@ -406,8 +415,7 @@ 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) { + list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { if (ptr->is_deleted) continue; if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) @@ -420,7 +428,6 @@ tomoyo_get_file_pattern(const struct tomoyo_path_info *filename) break; } } - up_read(&tomoyo_pattern_list_lock); if (pattern) filename = pattern; return filename; @@ -433,6 +440,8 @@ tomoyo_get_file_pattern(const struct tomoyo_path_info *filename) * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ int tomoyo_write_pattern_policy(char *data, const bool is_delete) { @@ -445,13 +454,14 @@ int tomoyo_write_pattern_policy(char *data, const bool is_delete) * @head: Pointer to "struct tomoyo_io_buffer". * * Returns true on success, false otherwise. + * + * Caller holds tomoyo_read_lock(). */ 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); @@ -462,7 +472,6 @@ bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head) if (!done) break; } - up_read(&tomoyo_pattern_list_lock); return done; } @@ -505,6 +514,8 @@ static DECLARE_RWSEM(tomoyo_no_rewrite_list_lock); * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_update_no_rewrite_entry(const char *pattern, const bool is_delete) @@ -519,7 +530,7 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, if (!saved_pattern) return -ENOMEM; down_write(&tomoyo_no_rewrite_list_lock); - list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) { + list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { if (ptr->pattern != saved_pattern) continue; ptr->is_deleted = is_delete; @@ -534,7 +545,7 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, if (!new_entry) goto out; new_entry->pattern = saved_pattern; - list_add_tail(&new_entry->list, &tomoyo_no_rewrite_list); + list_add_tail_rcu(&new_entry->list, &tomoyo_no_rewrite_list); error = 0; out: up_write(&tomoyo_no_rewrite_list_lock); @@ -548,14 +559,15 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, * * Returns true if @filename is specified by "deny_rewrite" directive, * false otherwise. + * + * Caller holds tomoyo_read_lock(). */ 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) { + list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { if (ptr->is_deleted) continue; if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) @@ -563,7 +575,6 @@ static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename) found = true; break; } - up_read(&tomoyo_no_rewrite_list_lock); return found; } @@ -574,6 +585,8 @@ static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename) * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete) { @@ -586,13 +599,14 @@ int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete) * @head: Pointer to "struct tomoyo_io_buffer". * * Returns true on success, false otherwise. + * + * Caller holds tomoyo_read_lock(). */ 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); @@ -603,7 +617,6 @@ bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head) if (!done) break; } - up_read(&tomoyo_no_rewrite_list_lock); return done; } @@ -621,6 +634,8 @@ bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head) * 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". + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_update_file_acl(const char *filename, u8 perm, struct tomoyo_domain_info * const domain, @@ -658,6 +673,8 @@ static int tomoyo_update_file_acl(const char *filename, u8 perm, * @may_use_pattern: True if patterned ACL is permitted. * * Returns 0 on success, -EPERM otherwise. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info * domain, @@ -669,8 +686,7 @@ static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info * 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) { + list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { struct tomoyo_single_path_acl_record *acl; if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) continue; @@ -693,7 +709,6 @@ static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info * error = 0; break; } - up_read(&tomoyo_domain_acl_info_list_lock); return error; } @@ -705,6 +720,8 @@ static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info * * @operation: Mode ("read" or "write" or "read/write" or "execute"). * * Returns 0 on success, -EPERM otherwise. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain, const struct tomoyo_path_info *filename, @@ -738,6 +755,8 @@ static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain, * @mode: Access control mode. * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain, const struct tomoyo_path_info *filename, @@ -791,6 +810,8 @@ static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain, * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, const bool is_delete) @@ -838,6 +859,8 @@ int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, struct tomoyo_domain_info * @@ -861,7 +884,7 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, down_write(&tomoyo_domain_acl_info_list_lock); if (is_delete) goto delete; - list_for_each_entry(ptr, &domain->acl_info_list, list) { + list_for_each_entry_rcu(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, @@ -894,12 +917,12 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, 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); + list_add_tail_rcu(&acl->head.list, &domain->acl_info_list); error = 0; goto out; delete: error = -ENOENT; - list_for_each_entry(ptr, &domain->acl_info_list, list) { + list_for_each_entry_rcu(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, @@ -934,6 +957,8 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, const char *filename2, @@ -959,7 +984,7 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, down_write(&tomoyo_domain_acl_info_list_lock); if (is_delete) goto delete; - list_for_each_entry(ptr, &domain->acl_info_list, list) { + list_for_each_entry_rcu(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, @@ -982,12 +1007,12 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, acl->perm = perm; acl->filename1 = saved_filename1; acl->filename2 = saved_filename2; - list_add_tail(&acl->head.list, &domain->acl_info_list); + list_add_tail_rcu(&acl->head.list, &domain->acl_info_list); error = 0; goto out; delete: error = -ENOENT; - list_for_each_entry(ptr, &domain->acl_info_list, list) { + list_for_each_entry_rcu(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, @@ -1014,6 +1039,8 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, * @filename: Filename to check. * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_check_single_path_acl(struct tomoyo_domain_info *domain, const u8 type, @@ -1033,6 +1060,8 @@ static int tomoyo_check_single_path_acl(struct tomoyo_domain_info *domain, * @filename2: Second filename to check. * * Returns 0 on success, -EPERM otherwise. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain, const u8 type, @@ -1047,8 +1076,7 @@ static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain, 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) { + list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { struct tomoyo_double_path_acl_record *acl; if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL) continue; @@ -1063,7 +1091,6 @@ static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain, error = 0; break; } - up_read(&tomoyo_domain_acl_info_list_lock); return error; } @@ -1076,6 +1103,8 @@ static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain, * @mode: Access control mode. * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info * const domain, u8 operation, @@ -1124,6 +1153,8 @@ static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info * * @filename: Check permission for "execute". * * Returns 0 on success, negativevalue otherwise. + * + * Caller holds tomoyo_read_lock(). */ int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, const struct tomoyo_path_info *filename) @@ -1152,6 +1183,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, struct tomoyo_path_info *buf; const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); const bool is_enforce = (mode == 3); + int idx; if (!mode || !path->mnt) return 0; @@ -1163,6 +1195,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, * don't call me. */ return 0; + idx = tomoyo_read_lock(); buf = tomoyo_get_path(path); if (!buf) goto out; @@ -1188,6 +1221,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, buf, mode); out: tomoyo_free(buf); + tomoyo_read_unlock(idx); if (!is_enforce) error = 0; return error; @@ -1209,9 +1243,11 @@ int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain, struct tomoyo_path_info *buf; const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); const bool is_enforce = (mode == 3); + int idx; if (!mode || !path->mnt) return 0; + idx = tomoyo_read_lock(); buf = tomoyo_get_path(path); if (!buf) goto out; @@ -1231,6 +1267,7 @@ int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain, mode); out: tomoyo_free(buf); + tomoyo_read_unlock(idx); if (!is_enforce) error = 0; return error; @@ -1251,9 +1288,12 @@ int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); const bool is_enforce = (mode == 3); struct tomoyo_path_info *buf; + int idx; if (!mode || !filp->f_path.mnt) return 0; + + idx = tomoyo_read_lock(); buf = tomoyo_get_path(&filp->f_path); if (!buf) goto out; @@ -1266,6 +1306,7 @@ int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, buf, mode); out: tomoyo_free(buf); + tomoyo_read_unlock(idx); if (!is_enforce) error = 0; return error; @@ -1290,9 +1331,11 @@ int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain, const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); const bool is_enforce = (mode == 3); const char *msg; + int idx; if (!mode || !path1->mnt || !path2->mnt) return 0; + idx = tomoyo_read_lock(); buf1 = tomoyo_get_path(path1); buf2 = tomoyo_get_path(path2); if (!buf1 || !buf2) @@ -1331,6 +1374,7 @@ int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain, out: tomoyo_free(buf1); tomoyo_free(buf2); + tomoyo_read_unlock(idx); if (!is_enforce) error = 0; return error; diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index e3c7aa0..62363b3 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -402,11 +402,13 @@ void __init tomoyo_realpath_init(void) INIT_LIST_HEAD(&tomoyo_name_list[i]); INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list); tomoyo_kernel_domain.domainname = tomoyo_save_name(TOMOYO_ROOT_NAME); - list_add_tail(&tomoyo_kernel_domain.list, &tomoyo_domain_list); - down_read(&tomoyo_domain_list_lock); + /* + * tomoyo_read_lock() is not needed because this function is + * called before the first "delete" request. + */ + list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list); if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain) panic("Can't register tomoyo_kernel_domain"); - up_read(&tomoyo_domain_list_lock); } /* Memory allocated for temporary purpose. */ diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index ad9555f..714daa3 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -76,8 +76,18 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm) * Execute permission is checked against pathname passed to do_execve() * using current domain. */ - if (!domain) - return tomoyo_find_next_domain(bprm); + if (!domain) { + /* + * We will need to protect whole execve() operation when GC + * starts kfree()ing "struct tomoyo_domain_info" because + * bprm->cred->security points to "struct tomoyo_domain_info" + * but "struct tomoyo_domain_info" does not have a refcounter. + */ + const int idx = tomoyo_read_lock(); + const int err = tomoyo_find_next_domain(bprm); + tomoyo_read_unlock(idx); + return err; + } /* * Read permission is checked against interpreters using next domain. * '1' is the result of open_to_namei_flags(O_RDONLY). @@ -278,6 +288,9 @@ static struct security_operations tomoyo_security_ops = { .sb_pivotroot = tomoyo_sb_pivotroot, }; +/* Lock for GC. */ +struct srcu_struct tomoyo_ss; + static int __init tomoyo_init(void) { struct cred *cred = (struct cred *) current_cred(); @@ -285,7 +298,8 @@ static int __init tomoyo_init(void) if (!security_module_enable(&tomoyo_security_ops)) return 0; /* register ourselves with the security framework */ - if (register_security(&tomoyo_security_ops)) + if (register_security(&tomoyo_security_ops) || + init_srcu_struct(&tomoyo_ss)) panic("Failure registering TOMOYO Linux"); printk(KERN_INFO "TOMOYO Linux initialized\n"); cred->security = &tomoyo_kernel_domain; -- cgit v1.1 From f737d95ddfea4df68a36ffc9231db4bf34b06d13 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Sun, 3 Jan 2010 21:16:32 +0900 Subject: TOMOYO: Replace rw_semaphore by mutex. Since readers no longer use down_read(), writers no longer need to use rw_semaphore. Replace individual rw_semaphore by single mutex. Signed-off-by: Tetsuo Handa Acked-by: Serge Hallyn Signed-off-by: James Morris --- security/tomoyo/common.c | 12 +++++++----- security/tomoyo/common.h | 5 ++--- security/tomoyo/domain.c | 20 ++++++++------------ security/tomoyo/file.c | 26 ++++++++++---------------- 4 files changed, 27 insertions(+), 36 deletions(-) (limited to 'security/tomoyo') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index f01b936..642e0e5 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -16,6 +16,9 @@ #include "common.h" #include "tomoyo.h" +/* Lock for protecting policy. */ +DEFINE_MUTEX(tomoyo_policy_lock); + /* Has loading policy done? */ bool tomoyo_policy_loaded; @@ -1086,7 +1089,6 @@ struct tomoyo_policy_manager_entry { * # cat /sys/kernel/security/tomoyo/manager */ static LIST_HEAD(tomoyo_policy_manager_list); -static DECLARE_RWSEM(tomoyo_policy_manager_list_lock); /** * tomoyo_update_manager_entry - Add a manager entry. @@ -1118,7 +1120,7 @@ static int tomoyo_update_manager_entry(const char *manager, saved_manager = tomoyo_save_name(manager); if (!saved_manager) return -ENOMEM; - down_write(&tomoyo_policy_manager_list_lock); + mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { if (ptr->manager != saved_manager) continue; @@ -1138,7 +1140,7 @@ static int tomoyo_update_manager_entry(const char *manager, list_add_tail_rcu(&new_entry->list, &tomoyo_policy_manager_list); error = 0; out: - up_write(&tomoyo_policy_manager_list_lock); + mutex_unlock(&tomoyo_policy_lock); return error; } @@ -1315,7 +1317,7 @@ static int tomoyo_delete_domain(char *domainname) name.name = domainname; tomoyo_fill_path_info(&name); - down_write(&tomoyo_domain_list_lock); + mutex_lock(&tomoyo_policy_lock); /* Is there an active domain? */ list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { /* Never delete tomoyo_kernel_domain */ @@ -1327,7 +1329,7 @@ static int tomoyo_delete_domain(char *domainname) domain->is_deleted = true; break; } - up_write(&tomoyo_domain_list_lock); + mutex_unlock(&tomoyo_policy_lock); return 0; } diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index c6f1392..874abf8 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -431,10 +431,9 @@ static inline bool tomoyo_is_invalid(const unsigned char c) /* The list for "struct tomoyo_domain_info". */ extern struct list_head tomoyo_domain_list; -extern struct rw_semaphore tomoyo_domain_list_lock; -/* Lock for domain->acl_info_list. */ -extern struct rw_semaphore tomoyo_domain_acl_info_list_lock; +/* Lock for protecting policy. */ +extern struct mutex tomoyo_policy_lock; /* Has /sbin/init started? */ extern bool tomoyo_policy_loaded; diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 2fd1901..7d0b0bc 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -58,7 +58,6 @@ struct tomoyo_domain_info tomoyo_kernel_domain; * exceptions. */ LIST_HEAD(tomoyo_domain_list); -DECLARE_RWSEM(tomoyo_domain_list_lock); /* * tomoyo_domain_initializer_entry is a structure which is used for holding @@ -206,7 +205,6 @@ const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain) * unless executed from " /etc/rc.d/init.d/httpd" domain. */ static LIST_HEAD(tomoyo_domain_initializer_list); -static DECLARE_RWSEM(tomoyo_domain_initializer_list_lock); /** * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list. @@ -247,7 +245,7 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, saved_program = tomoyo_save_name(program); if (!saved_program) return -ENOMEM; - down_write(&tomoyo_domain_initializer_list_lock); + mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { if (ptr->is_not != is_not || ptr->domainname != saved_domainname || @@ -271,7 +269,7 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, list_add_tail_rcu(&new_entry->list, &tomoyo_domain_initializer_list); error = 0; out: - up_write(&tomoyo_domain_initializer_list_lock); + mutex_unlock(&tomoyo_policy_lock); return error; } @@ -423,7 +421,6 @@ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * * explicitly specified by "initialize_domain". */ static LIST_HEAD(tomoyo_domain_keeper_list); -static DECLARE_RWSEM(tomoyo_domain_keeper_list_lock); /** * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list. @@ -464,7 +461,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, saved_domainname = tomoyo_save_name(domainname); if (!saved_domainname) return -ENOMEM; - down_write(&tomoyo_domain_keeper_list_lock); + mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { if (ptr->is_not != is_not || ptr->domainname != saved_domainname || @@ -488,7 +485,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, list_add_tail_rcu(&new_entry->list, &tomoyo_domain_keeper_list); error = 0; out: - up_write(&tomoyo_domain_keeper_list_lock); + mutex_unlock(&tomoyo_policy_lock); return error; } @@ -624,7 +621,6 @@ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, * execve() succeeds is calculated using /bin/cat rather than /bin/busybox . */ static LIST_HEAD(tomoyo_alias_list); -static DECLARE_RWSEM(tomoyo_alias_list_lock); /** * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list. @@ -654,7 +650,7 @@ static int tomoyo_update_alias_entry(const char *original_name, saved_aliased_name = tomoyo_save_name(aliased_name); if (!saved_original_name || !saved_aliased_name) return -ENOMEM; - down_write(&tomoyo_alias_list_lock); + mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { if (ptr->original_name != saved_original_name || ptr->aliased_name != saved_aliased_name) @@ -675,7 +671,7 @@ static int tomoyo_update_alias_entry(const char *original_name, list_add_tail_rcu(&new_entry->list, &tomoyo_alias_list); error = 0; out: - up_write(&tomoyo_alias_list_lock); + mutex_unlock(&tomoyo_policy_lock); return error; } @@ -745,7 +741,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * struct tomoyo_domain_info *domain = NULL; const struct tomoyo_path_info *saved_domainname; - down_write(&tomoyo_domain_list_lock); + mutex_lock(&tomoyo_policy_lock); domain = tomoyo_find_domain(domainname); if (domain) goto out; @@ -792,7 +788,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * list_add_tail_rcu(&domain->list, &tomoyo_domain_list); } out: - up_write(&tomoyo_domain_list_lock); + mutex_unlock(&tomoyo_policy_lock); return domain; } diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 3c47286..5d1689d 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -167,9 +167,6 @@ static struct tomoyo_path_info *tomoyo_get_path(struct path *path) 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 * @@ -204,7 +201,6 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, * belongs to. */ 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. @@ -229,7 +225,7 @@ static int tomoyo_update_globally_readable_entry(const char *filename, saved_filename = tomoyo_save_name(filename); if (!saved_filename) return -ENOMEM; - down_write(&tomoyo_globally_readable_list_lock); + mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { if (ptr->filename != saved_filename) continue; @@ -248,7 +244,7 @@ static int tomoyo_update_globally_readable_entry(const char *filename, list_add_tail_rcu(&new_entry->list, &tomoyo_globally_readable_list); error = 0; out: - up_write(&tomoyo_globally_readable_list_lock); + mutex_unlock(&tomoyo_policy_lock); return error; } @@ -352,7 +348,6 @@ bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head) * current process from accessing other process's information. */ static LIST_HEAD(tomoyo_pattern_list); -static DECLARE_RWSEM(tomoyo_pattern_list_lock); /** * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list. @@ -377,7 +372,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, saved_pattern = tomoyo_save_name(pattern); if (!saved_pattern) return -ENOMEM; - down_write(&tomoyo_pattern_list_lock); + mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { if (saved_pattern != ptr->pattern) continue; @@ -396,7 +391,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, list_add_tail_rcu(&new_entry->list, &tomoyo_pattern_list); error = 0; out: - up_write(&tomoyo_pattern_list_lock); + mutex_unlock(&tomoyo_policy_lock); return error; } @@ -505,7 +500,6 @@ bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head) * need to worry whether the file is already unlink()ed or not. */ 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. @@ -529,7 +523,7 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, saved_pattern = tomoyo_save_name(pattern); if (!saved_pattern) return -ENOMEM; - down_write(&tomoyo_no_rewrite_list_lock); + mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { if (ptr->pattern != saved_pattern) continue; @@ -548,7 +542,7 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, list_add_tail_rcu(&new_entry->list, &tomoyo_no_rewrite_list); error = 0; out: - up_write(&tomoyo_no_rewrite_list_lock); + mutex_unlock(&tomoyo_policy_lock); return error; } @@ -881,7 +875,7 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, saved_filename = tomoyo_save_name(filename); if (!saved_filename) return -ENOMEM; - down_write(&tomoyo_domain_acl_info_list_lock); + mutex_lock(&tomoyo_policy_lock); if (is_delete) goto delete; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { @@ -943,7 +937,7 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, break; } out: - up_write(&tomoyo_domain_acl_info_list_lock); + mutex_unlock(&tomoyo_policy_lock); return error; } @@ -981,7 +975,7 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, saved_filename2 = tomoyo_save_name(filename2); if (!saved_filename1 || !saved_filename2) return -ENOMEM; - down_write(&tomoyo_domain_acl_info_list_lock); + mutex_lock(&tomoyo_policy_lock); if (is_delete) goto delete; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { @@ -1027,7 +1021,7 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, break; } out: - up_write(&tomoyo_domain_acl_info_list_lock); + mutex_unlock(&tomoyo_policy_lock); return error; } -- cgit v1.1 From e41035a996356c257183e53a70abfb46fa84908b Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Tue, 5 Jan 2010 06:39:00 +0900 Subject: TOMOYO: Remove memory pool for string data. Currently, TOMOYO allocates memory for string data from memory pool allocated by kmalloc(PAGE_SIZE). But that makes it difficult to kfree() when garbage collector is added. Thus, remove memory pool and use kmalloc(strlen()). Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/realpath.c | 60 ++++++++-------------------------------------- 1 file changed, 10 insertions(+), 50 deletions(-) (limited to 'security/tomoyo') diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 62363b3..9105e5e 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -293,13 +293,6 @@ struct tomoyo_name_entry { struct tomoyo_path_info entry; }; -/* Structure for available memory region. */ -struct tomoyo_free_memory_block_list { - struct list_head list; - char *ptr; /* Pointer to a free area. */ - int len; /* Length of the area. */ -}; - /* * tomoyo_name_list is used for holding string data used by TOMOYO. * Since same string data is likely used for multiple times (e.g. @@ -314,52 +307,32 @@ static struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; * @name: The string to store into the permernent memory. * * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise. - * - * The RAM is shared, so NEVER try to modify or kfree() the returned name. */ const struct tomoyo_path_info *tomoyo_save_name(const char *name) { - static LIST_HEAD(fmb_list); static DEFINE_MUTEX(lock); struct tomoyo_name_entry *ptr; unsigned int hash; - /* fmb contains available size in bytes. - fmb is removed from the fmb_list when fmb->len becomes 0. */ - struct tomoyo_free_memory_block_list *fmb; int len; - char *cp; + int allocated_len; struct list_head *head; if (!name) return NULL; len = strlen(name) + 1; - if (len > TOMOYO_MAX_PATHNAME_LEN) { - printk(KERN_WARNING "ERROR: Name too long " - "for tomoyo_save_name().\n"); - return NULL; - } hash = full_name_hash((const unsigned char *) name, len - 1); head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)]; - mutex_lock(&lock); list_for_each_entry(ptr, head, list) { if (hash == ptr->entry.hash && !strcmp(name, ptr->entry.name)) goto out; } - list_for_each_entry(fmb, &fmb_list, list) { - if (len <= fmb->len) - goto ready; - } - if (!tomoyo_quota_for_savename || - tomoyo_allocated_memory_for_savename + PATH_MAX - <= tomoyo_quota_for_savename) - cp = kzalloc(PATH_MAX, GFP_KERNEL); - else - cp = NULL; - fmb = kzalloc(sizeof(*fmb), GFP_KERNEL); - if (!cp || !fmb) { - kfree(cp); - kfree(fmb); + ptr = kzalloc(sizeof(*ptr) + len, GFP_KERNEL); + allocated_len = ptr ? ksize(ptr) : 0; + if (!ptr || (tomoyo_quota_for_savename && + tomoyo_allocated_memory_for_savename + allocated_len + > tomoyo_quota_for_savename)) { + kfree(ptr); printk(KERN_WARNING "ERROR: Out of memory " "for tomoyo_save_name().\n"); if (!tomoyo_policy_loaded) @@ -367,24 +340,11 @@ const struct tomoyo_path_info *tomoyo_save_name(const char *name) ptr = NULL; goto out; } - tomoyo_allocated_memory_for_savename += PATH_MAX; - list_add(&fmb->list, &fmb_list); - fmb->ptr = cp; - fmb->len = PATH_MAX; - ready: - ptr = tomoyo_alloc_element(sizeof(*ptr)); - if (!ptr) - goto out; - ptr->entry.name = fmb->ptr; - memmove(fmb->ptr, name, len); + tomoyo_allocated_memory_for_savename += allocated_len; + ptr->entry.name = ((char *) ptr) + sizeof(*ptr); + memmove((char *) ptr->entry.name, name, len); tomoyo_fill_path_info(&ptr->entry); - fmb->ptr += len; - fmb->len -= len; list_add_tail(&ptr->list, head); - if (fmb->len == 0) { - list_del(&fmb->list); - kfree(fmb); - } out: mutex_unlock(&lock); return ptr ? &ptr->entry : NULL; -- cgit v1.1 From cd7bec6ad80188394a8ea857ff1aa3512fc2282a Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Tue, 5 Jan 2010 06:39:37 +0900 Subject: TOMOYO: Remove memory pool for list elements. Currently, TOMOYO allocates memory for list elements from memory pool allocated by kmalloc(PAGE_SIZE). But that makes it difficult to kfree() when garbage collector is added. Thus, remove memory pool and use kmalloc(sizeof()). Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/common.c | 41 ++++++----------------------- security/tomoyo/common.h | 2 -- security/tomoyo/domain.c | 58 ++++++++++++++--------------------------- security/tomoyo/file.c | 34 +++++++++++++++++------- security/tomoyo/realpath.c | 65 ++++++++++++++-------------------------------- security/tomoyo/realpath.h | 7 ++--- 6 files changed, 73 insertions(+), 134 deletions(-) (limited to 'security/tomoyo') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 642e0e5..e331e69 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -900,9 +900,11 @@ static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned ptr = tomoyo_profile_ptr[profile]; if (ptr) goto ok; - ptr = tomoyo_alloc_element(sizeof(*ptr)); - if (!ptr) + ptr = kmalloc(sizeof(*ptr), GFP_KERNEL); + if (!tomoyo_memory_ok(ptr)) { + kfree(ptr); goto ok; + } for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) ptr->value[i] = tomoyo_control_array[i].current_value; mb(); /* Avoid out-of-order execution. */ @@ -1120,6 +1122,7 @@ static int tomoyo_update_manager_entry(const char *manager, saved_manager = tomoyo_save_name(manager); if (!saved_manager) return -ENOMEM; + new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { if (ptr->manager != saved_manager) @@ -1132,15 +1135,16 @@ static int tomoyo_update_manager_entry(const char *manager, error = -ENOENT; goto out; } - new_entry = tomoyo_alloc_element(sizeof(*new_entry)); - if (!new_entry) + if (!tomoyo_memory_ok(new_entry)) goto out; new_entry->manager = saved_manager; new_entry->is_domain = is_domain; list_add_tail_rcu(&new_entry->list, &tomoyo_policy_manager_list); + new_entry = NULL; error = 0; out: mutex_unlock(&tomoyo_policy_lock); + kfree(new_entry); return error; } @@ -2148,35 +2152,6 @@ static int tomoyo_close_control(struct file *file) } /** - * tomoyo_alloc_acl_element - Allocate permanent memory for ACL entry. - * - * @acl_type: Type of ACL entry. - * - * Returns pointer to the ACL entry on success, NULL otherwise. - */ -void *tomoyo_alloc_acl_element(const u8 acl_type) -{ - int len; - struct tomoyo_acl_info *ptr; - - switch (acl_type) { - case TOMOYO_TYPE_SINGLE_PATH_ACL: - len = sizeof(struct tomoyo_single_path_acl_record); - break; - case TOMOYO_TYPE_DOUBLE_PATH_ACL: - len = sizeof(struct tomoyo_double_path_acl_record); - break; - default: - return NULL; - } - ptr = tomoyo_alloc_element(len); - if (!ptr) - return NULL; - ptr->type = acl_type; - return ptr; -} - -/** * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface. * * @inode: Pointer to "struct inode". diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 874abf8..610a6a0 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -376,8 +376,6 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * /* Check mode for specified functionality. */ unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, const u8 index); -/* Allocate memory for structures. */ -void *tomoyo_alloc_acl_element(const u8 acl_type); /* Fill in "struct tomoyo_path_info" members. */ void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); /* Run policy loader when /sbin/init starts. */ diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 7d0b0bc..a55a1cc 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -245,6 +245,7 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, saved_program = tomoyo_save_name(program); if (!saved_program) return -ENOMEM; + new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { if (ptr->is_not != is_not || @@ -259,17 +260,18 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, error = -ENOENT; goto out; } - new_entry = tomoyo_alloc_element(sizeof(*new_entry)); - if (!new_entry) + if (!tomoyo_memory_ok(new_entry)) goto out; new_entry->domainname = saved_domainname; new_entry->program = saved_program; new_entry->is_not = is_not; new_entry->is_last_name = is_last_name; list_add_tail_rcu(&new_entry->list, &tomoyo_domain_initializer_list); + new_entry = NULL; error = 0; out: mutex_unlock(&tomoyo_policy_lock); + kfree(new_entry); return error; } @@ -461,6 +463,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, saved_domainname = tomoyo_save_name(domainname); if (!saved_domainname) return -ENOMEM; + new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { if (ptr->is_not != is_not || @@ -475,17 +478,18 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, error = -ENOENT; goto out; } - new_entry = tomoyo_alloc_element(sizeof(*new_entry)); - if (!new_entry) + if (!tomoyo_memory_ok(new_entry)) goto out; new_entry->domainname = saved_domainname; new_entry->program = saved_program; new_entry->is_not = is_not; new_entry->is_last_name = is_last_name; list_add_tail_rcu(&new_entry->list, &tomoyo_domain_keeper_list); + new_entry = NULL; error = 0; out: mutex_unlock(&tomoyo_policy_lock); + kfree(new_entry); return error; } @@ -650,6 +654,7 @@ static int tomoyo_update_alias_entry(const char *original_name, saved_aliased_name = tomoyo_save_name(aliased_name); if (!saved_original_name || !saved_aliased_name) return -ENOMEM; + new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { if (ptr->original_name != saved_original_name || @@ -663,15 +668,16 @@ static int tomoyo_update_alias_entry(const char *original_name, error = -ENOENT; goto out; } - new_entry = tomoyo_alloc_element(sizeof(*new_entry)); - if (!new_entry) + if (!tomoyo_memory_ok(new_entry)) goto out; new_entry->original_name = saved_original_name; new_entry->aliased_name = saved_aliased_name; list_add_tail_rcu(&new_entry->list, &tomoyo_alias_list); + new_entry = NULL; error = 0; out: mutex_unlock(&tomoyo_policy_lock); + kfree(new_entry); return error; } @@ -738,7 +744,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * domainname, const u8 profile) { - struct tomoyo_domain_info *domain = NULL; + struct tomoyo_domain_info *domain; const struct tomoyo_path_info *saved_domainname; mutex_lock(&tomoyo_policy_lock); @@ -750,43 +756,17 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * saved_domainname = tomoyo_save_name(domainname); if (!saved_domainname) goto out; - /* Can I reuse memory of deleted domain? */ - list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { - struct task_struct *p; - struct tomoyo_acl_info *ptr; - bool flag; - if (!domain->is_deleted || - domain->domainname != saved_domainname) - continue; - flag = false; - read_lock(&tasklist_lock); - for_each_process(p) { - if (tomoyo_real_domain(p) != domain) - continue; - flag = true; - break; - } - read_unlock(&tasklist_lock); - if (flag) - continue; - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - ptr->type |= TOMOYO_ACL_DELETED; - } - tomoyo_set_domain_flag(domain, true, domain->flags); - domain->profile = profile; - domain->quota_warned = false; - mb(); /* Avoid out-of-order execution. */ - domain->is_deleted = false; - goto out; - } - /* No memory reusable. Create using new memory. */ - domain = tomoyo_alloc_element(sizeof(*domain)); - if (domain) { + domain = kmalloc(sizeof(*domain), GFP_KERNEL); + if (tomoyo_memory_ok(domain)) { INIT_LIST_HEAD(&domain->acl_info_list); domain->domainname = saved_domainname; domain->profile = profile; list_add_tail_rcu(&domain->list, &tomoyo_domain_list); + } else { + kfree(domain); + domain = NULL; } + out: mutex_unlock(&tomoyo_policy_lock); return domain; diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 5d1689d..075392c 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -225,6 +225,7 @@ static int tomoyo_update_globally_readable_entry(const char *filename, saved_filename = tomoyo_save_name(filename); if (!saved_filename) return -ENOMEM; + new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { if (ptr->filename != saved_filename) @@ -237,14 +238,15 @@ static int tomoyo_update_globally_readable_entry(const char *filename, error = -ENOENT; goto out; } - new_entry = tomoyo_alloc_element(sizeof(*new_entry)); - if (!new_entry) + if (!tomoyo_memory_ok(new_entry)) goto out; new_entry->filename = saved_filename; list_add_tail_rcu(&new_entry->list, &tomoyo_globally_readable_list); + new_entry = NULL; error = 0; out: mutex_unlock(&tomoyo_policy_lock); + kfree(new_entry); return error; } @@ -372,6 +374,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, saved_pattern = tomoyo_save_name(pattern); if (!saved_pattern) return -ENOMEM; + new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { if (saved_pattern != ptr->pattern) @@ -384,14 +387,15 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, error = -ENOENT; goto out; } - new_entry = tomoyo_alloc_element(sizeof(*new_entry)); - if (!new_entry) + if (!tomoyo_memory_ok(new_entry)) goto out; new_entry->pattern = saved_pattern; list_add_tail_rcu(&new_entry->list, &tomoyo_pattern_list); + new_entry = NULL; error = 0; out: mutex_unlock(&tomoyo_policy_lock); + kfree(new_entry); return error; } @@ -523,6 +527,7 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, saved_pattern = tomoyo_save_name(pattern); if (!saved_pattern) return -ENOMEM; + new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { if (ptr->pattern != saved_pattern) @@ -535,14 +540,15 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, error = -ENOENT; goto out; } - new_entry = tomoyo_alloc_element(sizeof(*new_entry)); - if (!new_entry) + if (!tomoyo_memory_ok(new_entry)) goto out; new_entry->pattern = saved_pattern; list_add_tail_rcu(&new_entry->list, &tomoyo_no_rewrite_list); + new_entry = NULL; error = 0; out: mutex_unlock(&tomoyo_policy_lock); + kfree(new_entry); return error; } @@ -901,9 +907,13 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, goto out; } /* Not found. Append it to the tail. */ - acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_SINGLE_PATH_ACL); - if (!acl) + acl = kmalloc(sizeof(*acl), GFP_KERNEL); + if (!tomoyo_memory_ok(acl)) { + kfree(acl); + acl = NULL; goto out; + } + acl->head.type = TOMOYO_TYPE_SINGLE_PATH_ACL; if (perm <= 0xFFFF) acl->perm = perm; else @@ -995,9 +1005,13 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, goto out; } /* Not found. Append it to the tail. */ - acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_DOUBLE_PATH_ACL); - if (!acl) + acl = kmalloc(sizeof(*acl), GFP_KERNEL); + if (!tomoyo_memory_ok(acl)) { + kfree(acl); + acl = NULL; goto out; + } + acl->head.type = TOMOYO_TYPE_DOUBLE_PATH_ACL; acl->perm = perm; acl->filename1 = saved_filename1; acl->filename2 = saved_filename2; diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 9105e5e..54226d5 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -212,57 +212,32 @@ static unsigned int tomoyo_allocated_memory_for_elements; static unsigned int tomoyo_quota_for_elements; /** - * tomoyo_alloc_element - Allocate permanent memory for structures. + * tomoyo_memory_ok - Check memory quota. * - * @size: Size in bytes. + * @ptr: Pointer to allocated memory. * - * Returns pointer to allocated memory on success, NULL otherwise. + * Returns true on success, false otherwise. * - * Memory has to be zeroed. - * The RAM is chunked, so NEVER try to kfree() the returned pointer. + * Caller holds tomoyo_policy_lock. + * Memory pointed by @ptr will be zeroed on success. */ -void *tomoyo_alloc_element(const unsigned int size) +bool tomoyo_memory_ok(void *ptr) { - static char *buf; - static DEFINE_MUTEX(lock); - static unsigned int buf_used_len = PATH_MAX; - char *ptr = NULL; - /*Assumes sizeof(void *) >= sizeof(long) is true. */ - const unsigned int word_aligned_size - = roundup(size, max(sizeof(void *), sizeof(long))); - if (word_aligned_size > PATH_MAX) - return NULL; - mutex_lock(&lock); - if (buf_used_len + word_aligned_size > PATH_MAX) { - if (!tomoyo_quota_for_elements || - tomoyo_allocated_memory_for_elements - + PATH_MAX <= tomoyo_quota_for_elements) - ptr = kzalloc(PATH_MAX, GFP_KERNEL); - if (!ptr) { - printk(KERN_WARNING "ERROR: Out of memory " - "for tomoyo_alloc_element().\n"); - if (!tomoyo_policy_loaded) - panic("MAC Initialization failed.\n"); - } else { - buf = ptr; - tomoyo_allocated_memory_for_elements += PATH_MAX; - buf_used_len = word_aligned_size; - ptr = buf; - } - } else if (word_aligned_size) { - int i; - ptr = buf + buf_used_len; - buf_used_len += word_aligned_size; - for (i = 0; i < word_aligned_size; i++) { - if (!ptr[i]) - continue; - printk(KERN_ERR "WARNING: Reserved memory was tainted! " - "The system might go wrong.\n"); - ptr[i] = '\0'; - } + int allocated_len = ptr ? ksize(ptr) : 0; + bool result = false; + if (!ptr || (tomoyo_quota_for_elements && + tomoyo_allocated_memory_for_elements + + allocated_len > tomoyo_quota_for_elements)) { + printk(KERN_WARNING "ERROR: Out of memory " + "for tomoyo_alloc_element().\n"); + if (!tomoyo_policy_loaded) + panic("MAC Initialization failed.\n"); + } else { + result = true; + tomoyo_allocated_memory_for_elements += allocated_len; + memset(ptr, 0, allocated_len); } - mutex_unlock(&lock); - return ptr; + return result; } /* Memory allocated for string data in bytes. */ diff --git a/security/tomoyo/realpath.h b/security/tomoyo/realpath.h index 78217a3..47b4f59 100644 --- a/security/tomoyo/realpath.h +++ b/security/tomoyo/realpath.h @@ -36,11 +36,8 @@ char *tomoyo_realpath_nofollow(const char *pathname); /* Same with tomoyo_realpath() except that the pathname is already solved. */ char *tomoyo_realpath_from_path(struct path *path); -/* - * Allocate memory for ACL entry. - * The RAM is chunked, so NEVER try to kfree() the returned pointer. - */ -void *tomoyo_alloc_element(const unsigned int size); +/* Check memory quota. */ +bool tomoyo_memory_ok(void *ptr); /* * Keep the given name on the RAM. -- cgit v1.1 From 8e2d39a1665e680c095545993aac2fcac6916eb9 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Tue, 26 Jan 2010 20:45:27 +0900 Subject: TOMOYO: Remove usage counter for temporary memory. TOMOYO was using own memory usage counter for detecting memory leak. But as kernel 2.6.31 introduced memory leak detection mechanism ( CONFIG_DEBUG_KMEMLEAK ), we no longer need to have own counter. We remove usage counter for memory used for permission checks, but we keep usage counter for memory used for policy so that we can apply quota. Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/common.c | 22 +++++++++++----------- security/tomoyo/common.h | 2 +- security/tomoyo/domain.c | 8 ++++---- security/tomoyo/file.c | 15 ++++++++------- security/tomoyo/realpath.c | 45 ++++----------------------------------------- security/tomoyo/realpath.h | 8 +------- 6 files changed, 29 insertions(+), 71 deletions(-) (limited to 'security/tomoyo') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index e331e69..ef66223 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -750,7 +750,7 @@ bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) * * Returns the tomoyo_realpath() of current process on success, NULL otherwise. * - * This function uses tomoyo_alloc(), so the caller must call tomoyo_free() + * This function uses kzalloc(), so the caller must call kfree() * if this function didn't return NULL. */ static const char *tomoyo_get_exe(void) @@ -1248,7 +1248,7 @@ static bool tomoyo_is_policy_manager(void) last_pid = pid; } } - tomoyo_free(exe); + kfree(exe); return found; } @@ -1931,7 +1931,7 @@ static int tomoyo_read_self_domain(struct tomoyo_io_buffer *head) */ static int tomoyo_open_control(const u8 type, struct file *file) { - struct tomoyo_io_buffer *head = tomoyo_alloc(sizeof(*head)); + struct tomoyo_io_buffer *head = kzalloc(sizeof(*head), GFP_KERNEL); if (!head) return -ENOMEM; @@ -1992,9 +1992,9 @@ static int tomoyo_open_control(const u8 type, struct file *file) } else { if (!head->readbuf_size) head->readbuf_size = 4096 * 2; - head->read_buf = tomoyo_alloc(head->readbuf_size); + head->read_buf = kzalloc(head->readbuf_size, GFP_KERNEL); if (!head->read_buf) { - tomoyo_free(head); + kfree(head); return -ENOMEM; } } @@ -2006,10 +2006,10 @@ static int tomoyo_open_control(const u8 type, struct file *file) head->write = NULL; } else if (head->write) { head->writebuf_size = 4096 * 2; - head->write_buf = tomoyo_alloc(head->writebuf_size); + head->write_buf = kzalloc(head->writebuf_size, GFP_KERNEL); if (!head->write_buf) { - tomoyo_free(head->read_buf); - tomoyo_free(head); + kfree(head->read_buf); + kfree(head); return -ENOMEM; } } @@ -2141,11 +2141,11 @@ static int tomoyo_close_control(struct file *file) tomoyo_read_unlock(head->reader_idx); /* Release memory used for policy I/O. */ - tomoyo_free(head->read_buf); + kfree(head->read_buf); head->read_buf = NULL; - tomoyo_free(head->write_buf); + kfree(head->write_buf); head->write_buf = NULL; - tomoyo_free(head); + kfree(head); head = NULL; file->private_data = NULL; return 0; diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 610a6a0..8b59ec8 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -89,7 +89,7 @@ struct tomoyo_path_info { * "struct tomoyo_path_info_with_data". */ struct tomoyo_path_info_with_data { - /* Keep "head" first, for this pointer is passed to tomoyo_free(). */ + /* Keep "head" first, for this pointer is passed to kfree(). */ struct tomoyo_path_info head; char barrier1[16]; /* Safeguard for overrun. */ char body[TOMOYO_MAX_PATHNAME_LEN]; diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index a55a1cc..3484397 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -787,7 +787,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) * This function assumes that the size of buffer returned by * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN. */ - struct tomoyo_page_buffer *tmp = tomoyo_alloc(sizeof(*tmp)); + struct tomoyo_page_buffer *tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); struct tomoyo_domain_info *old_domain = tomoyo_domain(); struct tomoyo_domain_info *domain = NULL; const char *old_domain_name = old_domain->domainname->name; @@ -902,8 +902,8 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) if (!domain) domain = old_domain; bprm->cred->security = domain; - tomoyo_free(real_program_name); - tomoyo_free(symlink_program_name); - tomoyo_free(tmp); + kfree(real_program_name); + kfree(symlink_program_name); + kfree(tmp); return retval; } diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index cfcb096..24af081 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -150,7 +150,8 @@ static bool tomoyo_strendswith(const char *name, const char *tail) static struct tomoyo_path_info *tomoyo_get_path(struct path *path) { int error; - struct tomoyo_path_info_with_data *buf = tomoyo_alloc(sizeof(*buf)); + struct tomoyo_path_info_with_data *buf = kzalloc(sizeof(*buf), + GFP_KERNEL); if (!buf) return NULL; @@ -162,7 +163,7 @@ static struct tomoyo_path_info *tomoyo_get_path(struct path *path) tomoyo_fill_path_info(&buf->head); return &buf->head; } - tomoyo_free(buf); + kfree(buf); return NULL; } @@ -1227,7 +1228,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, TOMOYO_TYPE_TRUNCATE_ACL, buf, mode); out: - tomoyo_free(buf); + kfree(buf); tomoyo_read_unlock(idx); if (!is_enforce) error = 0; @@ -1273,7 +1274,7 @@ int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain, error = tomoyo_check_single_path_permission2(domain, operation, buf, mode); out: - tomoyo_free(buf); + kfree(buf); tomoyo_read_unlock(idx); if (!is_enforce) error = 0; @@ -1312,7 +1313,7 @@ int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, TOMOYO_TYPE_REWRITE_ACL, buf, mode); out: - tomoyo_free(buf); + kfree(buf); tomoyo_read_unlock(idx); if (!is_enforce) error = 0; @@ -1379,8 +1380,8 @@ int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain, false); } out: - tomoyo_free(buf1); - tomoyo_free(buf2); + kfree(buf1); + kfree(buf2); tomoyo_read_unlock(idx); if (!is_enforce) error = 0; diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 54226d5..92460c7 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -150,12 +150,12 @@ int tomoyo_realpath_from_path2(struct path *path, char *newname, * * Returns the realpath of the given @path on success, NULL otherwise. * - * These functions use tomoyo_alloc(), so the caller must call tomoyo_free() + * These functions use kzalloc(), so the caller must call kfree() * if these functions didn't return NULL. */ char *tomoyo_realpath_from_path(struct path *path) { - char *buf = tomoyo_alloc(sizeof(struct tomoyo_page_buffer)); + char *buf = kzalloc(sizeof(struct tomoyo_page_buffer), GFP_KERNEL); BUILD_BUG_ON(sizeof(struct tomoyo_page_buffer) <= TOMOYO_MAX_PATHNAME_LEN - 1); @@ -164,7 +164,7 @@ char *tomoyo_realpath_from_path(struct path *path) if (tomoyo_realpath_from_path2(path, buf, TOMOYO_MAX_PATHNAME_LEN - 1) == 0) return buf; - tomoyo_free(buf); + kfree(buf); return NULL; } @@ -346,39 +346,6 @@ void __init tomoyo_realpath_init(void) panic("Can't register tomoyo_kernel_domain"); } -/* Memory allocated for temporary purpose. */ -static atomic_t tomoyo_dynamic_memory_size; - -/** - * tomoyo_alloc - Allocate memory for temporary purpose. - * - * @size: Size in bytes. - * - * Returns pointer to allocated memory on success, NULL otherwise. - */ -void *tomoyo_alloc(const size_t size) -{ - void *p = kzalloc(size, GFP_KERNEL); - if (p) - atomic_add(ksize(p), &tomoyo_dynamic_memory_size); - return p; -} - -/** - * tomoyo_free - Release memory allocated by tomoyo_alloc(). - * - * @p: Pointer returned by tomoyo_alloc(). May be NULL. - * - * Returns nothing. - */ -void tomoyo_free(const void *p) -{ - if (p) { - atomic_sub(ksize(p), &tomoyo_dynamic_memory_size); - kfree(p); - } -} - /** * tomoyo_read_memory_counter - Check for memory usage in bytes. * @@ -393,8 +360,6 @@ int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head) = tomoyo_allocated_memory_for_savename; const unsigned int private = tomoyo_allocated_memory_for_elements; - const unsigned int dynamic - = atomic_read(&tomoyo_dynamic_memory_size); char buffer[64]; memset(buffer, 0, sizeof(buffer)); @@ -412,9 +377,7 @@ int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head) else buffer[0] = '\0'; tomoyo_io_printf(head, "Private: %10u%s\n", private, buffer); - tomoyo_io_printf(head, "Dynamic: %10u\n", dynamic); - tomoyo_io_printf(head, "Total: %10u\n", - shared + private + dynamic); + tomoyo_io_printf(head, "Total: %10u\n", shared + private); head->read_eof = true; } return 0; diff --git a/security/tomoyo/realpath.h b/security/tomoyo/realpath.h index 47b4f59..da4f06f 100644 --- a/security/tomoyo/realpath.h +++ b/security/tomoyo/realpath.h @@ -25,7 +25,7 @@ int tomoyo_realpath_from_path2(struct path *path, char *newname, /* * Returns realpath(3) of the given pathname but ignores chroot'ed root. - * These functions use tomoyo_alloc(), so the caller must call tomoyo_free() + * These functions use kzalloc(), so the caller must call kfree() * if these functions didn't return NULL. */ char *tomoyo_realpath(const char *pathname); @@ -45,12 +45,6 @@ bool tomoyo_memory_ok(void *ptr); */ const struct tomoyo_path_info *tomoyo_save_name(const char *name); -/* Allocate memory for temporary use (e.g. permission checks). */ -void *tomoyo_alloc(const size_t size); - -/* Free memory allocated by tomoyo_alloc(). */ -void tomoyo_free(const void *p); - /* Check for memory usage. */ int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head); -- cgit v1.1 From ea13ddbad0eb4be9cdc406cd7e0804fa4011f6e4 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Wed, 3 Feb 2010 06:43:06 +0900 Subject: TOMOYO: Extract bitfield Since list elements are rounded up to kmalloc() size rather than sizeof(int), saving one byte by using bitfields is no longer helpful. Signed-off-by: Tetsuo Handa Acked-by: Serge Hallyn Signed-off-by: James Morris --- security/tomoyo/common.c | 16 +++++---------- security/tomoyo/common.h | 53 +++++++++++------------------------------------- security/tomoyo/domain.c | 25 +---------------------- security/tomoyo/file.c | 27 +++++++----------------- 4 files changed, 25 insertions(+), 96 deletions(-) (limited to 'security/tomoyo') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index ef66223..ae3ed73 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -842,9 +842,7 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain) if (!domain) return true; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - if (ptr->type & TOMOYO_ACL_DELETED) - continue; - switch (tomoyo_acl_type2(ptr)) { + switch (ptr->type) { struct tomoyo_single_path_acl_record *acl; u32 perm; u8 i; @@ -1384,8 +1382,7 @@ static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head) return 0; } if (!strcmp(data, TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) { - tomoyo_set_domain_flag(domain, is_delete, - TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ); + domain->ignore_global_allow_read = !is_delete; return 0; } return tomoyo_write_file_policy(data, domain, is_delete); @@ -1486,10 +1483,8 @@ static bool tomoyo_print_double_path_acl(struct tomoyo_io_buffer *head, static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, struct tomoyo_acl_info *ptr) { - const u8 acl_type = tomoyo_acl_type2(ptr); + const u8 acl_type = ptr->type; - if (acl_type & TOMOYO_ACL_DELETED) - return true; if (acl_type == TOMOYO_TYPE_SINGLE_PATH_ACL) { struct tomoyo_single_path_acl_record *acl = container_of(ptr, @@ -1540,10 +1535,9 @@ static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head) /* Print domainname and flags. */ if (domain->quota_warned) quota_exceeded = "quota_exceeded\n"; - if (domain->flags & TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED) + if (domain->transition_failed) transition_failed = "transition_failed\n"; - if (domain->flags & - TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ) + if (domain->ignore_global_allow_read) ignore_global_allow_read = TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n"; done = tomoyo_io_printf(head, "%s\n" TOMOYO_KEYWORD_USE_PROFILE diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 8b59ec8..509ced9c 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -101,11 +101,9 @@ struct tomoyo_path_info_with_data { * * (1) "list" which is linked to the ->acl_info_list of * "struct tomoyo_domain_info" - * (2) "type" which tells - * (a) type & 0x7F : type of the entry (either - * "struct tomoyo_single_path_acl_record" or - * "struct tomoyo_double_path_acl_record") - * (b) type & 0x80 : whether the entry is marked as "deleted". + * (2) "type" which tells type of the entry (either + * "struct tomoyo_single_path_acl_record" or + * "struct tomoyo_double_path_acl_record"). * * Packing "struct tomoyo_acl_info" allows * "struct tomoyo_single_path_acl_record" to embed "u8" + "u16" and @@ -114,17 +112,9 @@ struct tomoyo_path_info_with_data { */ struct tomoyo_acl_info { struct list_head list; - /* - * Type of this ACL entry. - * - * MSB is is_deleted flag. - */ u8 type; } __packed; -/* This ACL entry is deleted. */ -#define TOMOYO_ACL_DELETED 0x80 - /* * tomoyo_domain_info is a structure which is used for holding permissions * (e.g. "allow_read /lib/libc-2.5.so") given to each domain. @@ -138,7 +128,13 @@ struct tomoyo_acl_info { * "deleted", false otherwise. * (6) "quota_warned" is a bool which is used for suppressing warning message * when learning mode learned too much entries. - * (7) "flags" which remembers this domain's attributes. + * (7) "ignore_global_allow_read" is a bool which is true if this domain + * should ignore "allow_read" directive in exception policy. + * (8) "transition_failed" is a bool which is set to true when this domain was + * unable to create a new domain at tomoyo_find_next_domain() because the + * name of the domain to be created was too long or it could not allocate + * memory. If set to true, more than one process continued execve() + * without domain transition. * * A domain's lifecycle is an analogy of files on / directory. * Multiple domains with the same domainname cannot be created (as with @@ -155,23 +151,13 @@ struct tomoyo_domain_info { u8 profile; /* Profile number to use. */ bool is_deleted; /* Delete flag. */ bool quota_warned; /* Quota warnning flag. */ - /* DOMAIN_FLAGS_*. Use tomoyo_set_domain_flag() to modify. */ - u8 flags; + bool ignore_global_allow_read; /* Ignore "allow_read" flag. */ + bool transition_failed; /* Domain transition failed flag. */ }; /* Profile number is an integer between 0 and 255. */ #define TOMOYO_MAX_PROFILES 256 -/* Ignore "allow_read" directive in exception policy. */ -#define TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ 1 -/* - * This domain was unable to create a new domain at tomoyo_find_next_domain() - * because the name of the domain to be created was too long or - * it could not allocate memory. - * More than one process continued execve() without domain transition. - */ -#define TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED 2 - /* * tomoyo_single_path_acl_record is a structure which is used for holding an * entry with one pathname operation (e.g. open(), mkdir()). @@ -380,9 +366,6 @@ unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); /* Run policy loader when /sbin/init starts. */ void tomoyo_load_policy(const char *filename); -/* Change "struct tomoyo_domain_info"->flags. */ -void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain, - const bool is_delete, const u8 flags); /* strcmp() for "struct tomoyo_path_info" structure. */ static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a, @@ -391,18 +374,6 @@ static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a, return a->hash != b->hash || strcmp(a->name, b->name); } -/* Get type of an ACL entry. */ -static inline u8 tomoyo_acl_type1(struct tomoyo_acl_info *ptr) -{ - return ptr->type & ~TOMOYO_ACL_DELETED; -} - -/* Get type of an ACL entry. */ -static inline u8 tomoyo_acl_type2(struct tomoyo_acl_info *ptr) -{ - return ptr->type; -} - /** * tomoyo_is_valid - Check whether the character is a valid char. * diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 3484397..ec612ae 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -130,28 +130,6 @@ struct tomoyo_alias_entry { }; /** - * tomoyo_set_domain_flag - Set or clear domain's attribute flags. - * - * @domain: Pointer to "struct tomoyo_domain_info". - * @is_delete: True if it is a delete request. - * @flags: Flags to set or clear. - * - * Returns nothing. - */ -void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain, - const bool is_delete, const u8 flags) -{ - /* We need to serialize because this is bitfield operation. */ - static DEFINE_SPINLOCK(lock); - spin_lock(&lock); - if (!is_delete) - domain->flags |= flags; - else - domain->flags &= ~flags; - spin_unlock(&lock); -} - -/** * tomoyo_get_last_name - Get last component of a domainname. * * @domain: Pointer to "struct tomoyo_domain_info". @@ -896,8 +874,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) if (is_enforce) retval = -EPERM; else - tomoyo_set_domain_flag(old_domain, false, - TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED); + old_domain->transition_failed = true; out: if (!domain) domain = old_domain; diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 24af081..84c821a 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -688,7 +688,7 @@ static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info * list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { struct tomoyo_single_path_acl_record *acl; - if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) + if (ptr->type != TOMOYO_TYPE_SINGLE_PATH_ACL) continue; acl = container_of(ptr, struct tomoyo_single_path_acl_record, head); @@ -770,8 +770,7 @@ static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain, 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 + if (error && perm == 4 && !domain->ignore_global_allow_read && tomoyo_is_globally_readable_file(filename)) error = 0; if (perm == 6) @@ -885,15 +884,12 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, if (is_delete) goto delete; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) + if (ptr->type != 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; if (perm <= 0xFFFF) acl->perm |= perm; else @@ -902,7 +898,6 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, 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; } @@ -927,7 +922,7 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, delete: error = -ENOENT; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) + if (ptr->type != TOMOYO_TYPE_SINGLE_PATH_ACL) continue; acl = container_of(ptr, struct tomoyo_single_path_acl_record, head); @@ -941,8 +936,6 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, 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 && !acl->perm_high) - ptr->type |= TOMOYO_ACL_DELETED; error = 0; break; } @@ -989,18 +982,14 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, if (is_delete) goto delete; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL) + if (ptr->type != 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; } @@ -1021,7 +1010,7 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, delete: error = -ENOENT; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL) + if (ptr->type != TOMOYO_TYPE_DOUBLE_PATH_ACL) continue; acl = container_of(ptr, struct tomoyo_double_path_acl_record, head); @@ -1029,8 +1018,6 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, acl->filename2 != saved_filename2) continue; acl->perm &= ~perm; - if (!acl->perm) - ptr->type |= TOMOYO_ACL_DELETED; error = 0; break; } @@ -1086,7 +1073,7 @@ static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain, return 0; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { struct tomoyo_double_path_acl_record *acl; - if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL) + if (ptr->type != TOMOYO_TYPE_DOUBLE_PATH_ACL) continue; acl = container_of(ptr, struct tomoyo_double_path_acl_record, head); -- cgit v1.1 From ca0b7df3374c5566468c17f26fa2dfd3fe3c6a37 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Sun, 7 Feb 2010 20:23:59 +0900 Subject: TOMOYO: Reduce lines by using common path for addition and deletion. Since the codes for adding an entry and removing an entry are similar, we can save some lines by using "if (is_delete) { ... } else { ... }" branches. Signed-off-by: Tetsuo Handa Acked-by: Serge Hallyn Signed-off-by: James Morris --- security/tomoyo/common.c | 28 +++--- security/tomoyo/domain.c | 147 +++++++++++++++-------------- security/tomoyo/file.c | 234 ++++++++++++++++++++--------------------------- 3 files changed, 183 insertions(+), 226 deletions(-) (limited to 'security/tomoyo') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index ae3ed73..a53ee05 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -1103,10 +1103,10 @@ static LIST_HEAD(tomoyo_policy_manager_list); static int tomoyo_update_manager_entry(const char *manager, const bool is_delete) { - struct tomoyo_policy_manager_entry *new_entry; + struct tomoyo_policy_manager_entry *entry = NULL; struct tomoyo_policy_manager_entry *ptr; const struct tomoyo_path_info *saved_manager; - int error = -ENOMEM; + int error = is_delete ? -ENOENT : -ENOMEM; bool is_domain = false; if (tomoyo_is_domain_def(manager)) { @@ -1120,29 +1120,25 @@ static int tomoyo_update_manager_entry(const char *manager, saved_manager = tomoyo_save_name(manager); if (!saved_manager) return -ENOMEM; - new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); + if (!is_delete) + entry = kmalloc(sizeof(*entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { if (ptr->manager != saved_manager) continue; ptr->is_deleted = is_delete; error = 0; - goto out; + break; } - if (is_delete) { - error = -ENOENT; - goto out; + if (!is_delete && error && tomoyo_memory_ok(entry)) { + entry->manager = saved_manager; + entry->is_domain = is_domain; + list_add_tail_rcu(&entry->list, &tomoyo_policy_manager_list); + entry = NULL; + error = 0; } - if (!tomoyo_memory_ok(new_entry)) - goto out; - new_entry->manager = saved_manager; - new_entry->is_domain = is_domain; - list_add_tail_rcu(&new_entry->list, &tomoyo_policy_manager_list); - new_entry = NULL; - error = 0; - out: mutex_unlock(&tomoyo_policy_lock); - kfree(new_entry); + kfree(entry); return error; } diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index ec612ae..229de1e 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -201,11 +201,11 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, const bool is_not, const bool is_delete) { - struct tomoyo_domain_initializer_entry *new_entry; + struct tomoyo_domain_initializer_entry *entry = NULL; struct tomoyo_domain_initializer_entry *ptr; const struct tomoyo_path_info *saved_program; const struct tomoyo_path_info *saved_domainname = NULL; - int error = -ENOMEM; + int error = is_delete ? -ENOENT : -ENOMEM; bool is_last_name = false; if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__)) @@ -218,12 +218,13 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, return -EINVAL; saved_domainname = tomoyo_save_name(domainname); if (!saved_domainname) - return -ENOMEM; + goto out; } saved_program = tomoyo_save_name(program); if (!saved_program) - return -ENOMEM; - new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); + goto out; + if (!is_delete) + entry = kmalloc(sizeof(*entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { if (ptr->is_not != is_not || @@ -232,24 +233,21 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, continue; ptr->is_deleted = is_delete; error = 0; - goto out; + break; } - if (is_delete) { - error = -ENOENT; - goto out; + if (!is_delete && error && tomoyo_memory_ok(entry)) { + entry->domainname = saved_domainname; + entry->program = saved_program; + entry->is_not = is_not; + entry->is_last_name = is_last_name; + list_add_tail_rcu(&entry->list, + &tomoyo_domain_initializer_list); + entry = NULL; + error = 0; } - if (!tomoyo_memory_ok(new_entry)) - goto out; - new_entry->domainname = saved_domainname; - new_entry->program = saved_program; - new_entry->is_not = is_not; - new_entry->is_last_name = is_last_name; - list_add_tail_rcu(&new_entry->list, &tomoyo_domain_initializer_list); - new_entry = NULL; - error = 0; - out: mutex_unlock(&tomoyo_policy_lock); - kfree(new_entry); + out: + kfree(entry); return error; } @@ -419,11 +417,11 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, const bool is_not, const bool is_delete) { - struct tomoyo_domain_keeper_entry *new_entry; + struct tomoyo_domain_keeper_entry *entry = NULL; struct tomoyo_domain_keeper_entry *ptr; const struct tomoyo_path_info *saved_domainname; const struct tomoyo_path_info *saved_program = NULL; - int error = -ENOMEM; + int error = is_delete ? -ENOENT : -ENOMEM; bool is_last_name = false; if (!tomoyo_is_domain_def(domainname) && @@ -436,12 +434,13 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, return -EINVAL; saved_program = tomoyo_save_name(program); if (!saved_program) - return -ENOMEM; + goto out; } saved_domainname = tomoyo_save_name(domainname); if (!saved_domainname) - return -ENOMEM; - new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); + goto out; + if (!is_delete) + entry = kmalloc(sizeof(*entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { if (ptr->is_not != is_not || @@ -450,24 +449,20 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, continue; ptr->is_deleted = is_delete; error = 0; - goto out; + break; } - if (is_delete) { - error = -ENOENT; - goto out; + if (!is_delete && error && tomoyo_memory_ok(entry)) { + entry->domainname = saved_domainname; + entry->program = saved_program; + entry->is_not = is_not; + entry->is_last_name = is_last_name; + list_add_tail_rcu(&entry->list, &tomoyo_domain_keeper_list); + entry = NULL; + error = 0; } - if (!tomoyo_memory_ok(new_entry)) - goto out; - new_entry->domainname = saved_domainname; - new_entry->program = saved_program; - new_entry->is_not = is_not; - new_entry->is_last_name = is_last_name; - list_add_tail_rcu(&new_entry->list, &tomoyo_domain_keeper_list); - new_entry = NULL; - error = 0; - out: mutex_unlock(&tomoyo_policy_lock); - kfree(new_entry); + out: + kfree(entry); return error; } @@ -619,11 +614,11 @@ static int tomoyo_update_alias_entry(const char *original_name, const char *aliased_name, const bool is_delete) { - struct tomoyo_alias_entry *new_entry; + struct tomoyo_alias_entry *entry = NULL; struct tomoyo_alias_entry *ptr; const struct tomoyo_path_info *saved_original_name; const struct tomoyo_path_info *saved_aliased_name; - int error = -ENOMEM; + int error = is_delete ? -ENOENT : -ENOMEM; if (!tomoyo_is_correct_path(original_name, 1, -1, -1, __func__) || !tomoyo_is_correct_path(aliased_name, 1, -1, -1, __func__)) @@ -631,8 +626,9 @@ static int tomoyo_update_alias_entry(const char *original_name, saved_original_name = tomoyo_save_name(original_name); saved_aliased_name = tomoyo_save_name(aliased_name); if (!saved_original_name || !saved_aliased_name) - return -ENOMEM; - new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); + goto out; + if (!is_delete) + entry = kmalloc(sizeof(*entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { if (ptr->original_name != saved_original_name || @@ -640,22 +636,18 @@ static int tomoyo_update_alias_entry(const char *original_name, continue; ptr->is_deleted = is_delete; error = 0; - goto out; + break; } - if (is_delete) { - error = -ENOENT; - goto out; + if (!is_delete && error && tomoyo_memory_ok(entry)) { + entry->original_name = saved_original_name; + entry->aliased_name = saved_aliased_name; + list_add_tail_rcu(&entry->list, &tomoyo_alias_list); + entry = NULL; + error = 0; } - if (!tomoyo_memory_ok(new_entry)) - goto out; - new_entry->original_name = saved_original_name; - new_entry->aliased_name = saved_aliased_name; - list_add_tail_rcu(&new_entry->list, &tomoyo_alias_list); - new_entry = NULL; - error = 0; - out: mutex_unlock(&tomoyo_policy_lock); - kfree(new_entry); + out: + kfree(entry); return error; } @@ -722,32 +714,37 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * domainname, const u8 profile) { + struct tomoyo_domain_info *entry; struct tomoyo_domain_info *domain; const struct tomoyo_path_info *saved_domainname; + bool found = false; - mutex_lock(&tomoyo_policy_lock); - domain = tomoyo_find_domain(domainname); - if (domain) - goto out; if (!tomoyo_is_correct_domain(domainname, __func__)) - goto out; + return NULL; saved_domainname = tomoyo_save_name(domainname); if (!saved_domainname) - goto out; - domain = kmalloc(sizeof(*domain), GFP_KERNEL); - if (tomoyo_memory_ok(domain)) { - INIT_LIST_HEAD(&domain->acl_info_list); - domain->domainname = saved_domainname; - domain->profile = profile; - list_add_tail_rcu(&domain->list, &tomoyo_domain_list); - } else { - kfree(domain); - domain = NULL; + return NULL; + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + mutex_lock(&tomoyo_policy_lock); + list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { + if (domain->is_deleted || + tomoyo_pathcmp(saved_domainname, domain->domainname)) + continue; + found = true; + break; + } + if (!found && tomoyo_memory_ok(entry)) { + INIT_LIST_HEAD(&entry->acl_info_list); + entry->domainname = saved_domainname; + entry->profile = profile; + list_add_tail_rcu(&entry->list, &tomoyo_domain_list); + domain = entry; + entry = NULL; + found = true; } - - out: mutex_unlock(&tomoyo_policy_lock); - return domain; + kfree(entry); + return found ? domain : NULL; } /** diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 84c821a..f4a2771 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -215,38 +215,34 @@ static LIST_HEAD(tomoyo_globally_readable_list); 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 *entry = NULL; struct tomoyo_globally_readable_file_entry *ptr; const struct tomoyo_path_info *saved_filename; - int error = -ENOMEM; + int error = is_delete ? -ENOENT : -ENOMEM; if (!tomoyo_is_correct_path(filename, 1, 0, -1, __func__)) return -EINVAL; saved_filename = tomoyo_save_name(filename); if (!saved_filename) return -ENOMEM; - new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); + if (!is_delete) + entry = kmalloc(sizeof(*entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { if (ptr->filename != saved_filename) continue; ptr->is_deleted = is_delete; error = 0; - goto out; + break; } - if (is_delete) { - error = -ENOENT; - goto out; + if (!is_delete && error && tomoyo_memory_ok(entry)) { + entry->filename = saved_filename; + list_add_tail_rcu(&entry->list, &tomoyo_globally_readable_list); + entry = NULL; + error = 0; } - if (!tomoyo_memory_ok(new_entry)) - goto out; - new_entry->filename = saved_filename; - list_add_tail_rcu(&new_entry->list, &tomoyo_globally_readable_list); - new_entry = NULL; - error = 0; - out: mutex_unlock(&tomoyo_policy_lock); - kfree(new_entry); + kfree(entry); return error; } @@ -364,38 +360,35 @@ static LIST_HEAD(tomoyo_pattern_list); static int tomoyo_update_file_pattern_entry(const char *pattern, const bool is_delete) { - struct tomoyo_pattern_entry *new_entry; + struct tomoyo_pattern_entry *entry = NULL; struct tomoyo_pattern_entry *ptr; const struct tomoyo_path_info *saved_pattern; - int error = -ENOMEM; + int error = is_delete ? -ENOENT : -ENOMEM; - if (!tomoyo_is_correct_path(pattern, 0, 1, 0, __func__)) - return -EINVAL; saved_pattern = tomoyo_save_name(pattern); if (!saved_pattern) - return -ENOMEM; - new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); + return error; + if (!saved_pattern->is_patterned) + goto out; + if (!is_delete) + entry = kmalloc(sizeof(*entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { if (saved_pattern != ptr->pattern) continue; ptr->is_deleted = is_delete; error = 0; - goto out; + break; } - if (is_delete) { - error = -ENOENT; - goto out; + if (!is_delete && error && tomoyo_memory_ok(entry)) { + entry->pattern = saved_pattern; + list_add_tail_rcu(&entry->list, &tomoyo_pattern_list); + entry = NULL; + error = 0; } - if (!tomoyo_memory_ok(new_entry)) - goto out; - new_entry->pattern = saved_pattern; - list_add_tail_rcu(&new_entry->list, &tomoyo_pattern_list); - new_entry = NULL; - error = 0; - out: mutex_unlock(&tomoyo_policy_lock); - kfree(new_entry); + out: + kfree(entry); return error; } @@ -518,37 +511,34 @@ static LIST_HEAD(tomoyo_no_rewrite_list); static int tomoyo_update_no_rewrite_entry(const char *pattern, const bool is_delete) { - struct tomoyo_no_rewrite_entry *new_entry, *ptr; + struct tomoyo_no_rewrite_entry *entry = NULL; + struct tomoyo_no_rewrite_entry *ptr; const struct tomoyo_path_info *saved_pattern; - int error = -ENOMEM; + int error = is_delete ? -ENOENT : -ENOMEM; if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__)) return -EINVAL; saved_pattern = tomoyo_save_name(pattern); if (!saved_pattern) - return -ENOMEM; - new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); + return error; + if (!is_delete) + entry = kmalloc(sizeof(*entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { if (ptr->pattern != saved_pattern) continue; ptr->is_deleted = is_delete; error = 0; - goto out; + break; } - if (is_delete) { - error = -ENOENT; - goto out; + if (!is_delete && error && tomoyo_memory_ok(entry)) { + entry->pattern = saved_pattern; + list_add_tail_rcu(&entry->list, &tomoyo_no_rewrite_list); + entry = NULL; + error = 0; } - if (!tomoyo_memory_ok(new_entry)) - goto out; - new_entry->pattern = saved_pattern; - list_add_tail_rcu(&new_entry->list, &tomoyo_no_rewrite_list); - new_entry = NULL; - error = 0; - out: mutex_unlock(&tomoyo_policy_lock); - kfree(new_entry); + kfree(entry); return error; } @@ -869,8 +859,8 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, (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; + struct tomoyo_single_path_acl_record *entry = NULL; + int error = is_delete ? -ENOENT : -ENOMEM; const u32 perm = 1 << type; if (!domain) @@ -880,67 +870,55 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, saved_filename = tomoyo_save_name(filename); if (!saved_filename) return -ENOMEM; + if (!is_delete) + entry = kmalloc(sizeof(*entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); - if (is_delete) - goto delete; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { + struct tomoyo_single_path_acl_record *acl = + container_of(ptr, struct tomoyo_single_path_acl_record, + head); if (ptr->type != TOMOYO_TYPE_SINGLE_PATH_ACL) continue; - acl = container_of(ptr, struct tomoyo_single_path_acl_record, - head); if (acl->filename != saved_filename) continue; - 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 (is_delete) { + 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; + } else { + 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; + } error = 0; - goto out; - } - /* Not found. Append it to the tail. */ - acl = kmalloc(sizeof(*acl), GFP_KERNEL); - if (!tomoyo_memory_ok(acl)) { - kfree(acl); - acl = NULL; - goto out; + break; } - acl->head.type = TOMOYO_TYPE_SINGLE_PATH_ACL; - 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; - list_add_tail_rcu(&acl->head.list, &domain->acl_info_list); - error = 0; - goto out; - delete: - error = -ENOENT; - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - if (ptr->type != TOMOYO_TYPE_SINGLE_PATH_ACL) - continue; - acl = container_of(ptr, struct tomoyo_single_path_acl_record, - head); - if (acl->filename != saved_filename) - continue; + if (!is_delete && error && tomoyo_memory_ok(entry)) { + entry->head.type = TOMOYO_TYPE_SINGLE_PATH_ACL; if (perm <= 0xFFFF) - acl->perm &= ~perm; + entry->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; + entry->perm_high = (perm >> 16); + if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL)) + entry->perm |= rw_mask; + entry->filename = saved_filename; + list_add_tail_rcu(&entry->head.list, &domain->acl_info_list); + entry = NULL; error = 0; - break; } - out: mutex_unlock(&tomoyo_policy_lock); + kfree(entry); return error; } @@ -965,8 +943,8 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, 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; + struct tomoyo_double_path_acl_record *entry = NULL; + int error = is_delete ? -ENOENT : -ENOMEM; const u8 perm = 1 << type; if (!domain) @@ -977,52 +955,38 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, saved_filename1 = tomoyo_save_name(filename1); saved_filename2 = tomoyo_save_name(filename2); if (!saved_filename1 || !saved_filename2) - return -ENOMEM; + goto out; + if (!is_delete) + entry = kmalloc(sizeof(*entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); - if (is_delete) - goto delete; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { + struct tomoyo_double_path_acl_record *acl = + container_of(ptr, struct tomoyo_double_path_acl_record, + head); if (ptr->type != 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 (is_delete) + acl->perm &= ~perm; + else + acl->perm |= perm; error = 0; - goto out; - } - /* Not found. Append it to the tail. */ - acl = kmalloc(sizeof(*acl), GFP_KERNEL); - if (!tomoyo_memory_ok(acl)) { - kfree(acl); - acl = NULL; - goto out; + break; } - acl->head.type = TOMOYO_TYPE_DOUBLE_PATH_ACL; - acl->perm = perm; - acl->filename1 = saved_filename1; - acl->filename2 = saved_filename2; - list_add_tail_rcu(&acl->head.list, &domain->acl_info_list); - error = 0; - goto out; - delete: - error = -ENOENT; - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - if (ptr->type != 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 (!is_delete && error && tomoyo_memory_ok(entry)) { + entry->head.type = TOMOYO_TYPE_DOUBLE_PATH_ACL; + entry->perm = perm; + entry->filename1 = saved_filename1; + entry->filename2 = saved_filename2; + list_add_tail_rcu(&entry->head.list, &domain->acl_info_list); + entry = NULL; error = 0; - break; } - out: mutex_unlock(&tomoyo_policy_lock); + out: + kfree(entry); return error; } -- cgit v1.1 From bf24fb016c861b7f52be0c36c4cedd3e89afa2e2 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Thu, 11 Feb 2010 09:41:58 +0900 Subject: TOMOYO: Add refcounter on string data. Add refcounter to "struct tomoyo_name_entry" and replace tomoyo_save_name() with tomoyo_get_name()/tomoyo_put_name() pair so that we can kfree() when garbage collector is added. Signed-off-by: Tetsuo Handa Acked-by: Serge Hallyn Signed-off-by: James Morris --- security/tomoyo/common.c | 10 +++++++--- security/tomoyo/domain.c | 32 +++++++++++++++++++++++--------- security/tomoyo/file.c | 24 ++++++++++++++++++------ security/tomoyo/realpath.c | 30 +++++++++--------------------- security/tomoyo/realpath.h | 21 ++++++++++++++++++++- 5 files changed, 77 insertions(+), 40 deletions(-) (limited to 'security/tomoyo') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index a53ee05..0c7ea51 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -12,8 +12,8 @@ #include #include #include -#include "realpath.h" #include "common.h" +#include "realpath.h" #include "tomoyo.h" /* Lock for protecting policy. */ @@ -943,7 +943,9 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head) return -EINVAL; *cp = '\0'; if (!strcmp(data, "COMMENT")) { - profile->comment = tomoyo_save_name(cp + 1); + const struct tomoyo_path_info *old_comment = profile->comment; + profile->comment = tomoyo_get_name(cp + 1); + tomoyo_put_name(old_comment); return 0; } for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) { @@ -1117,7 +1119,7 @@ static int tomoyo_update_manager_entry(const char *manager, if (!tomoyo_is_correct_path(manager, 1, -1, -1, __func__)) return -EINVAL; } - saved_manager = tomoyo_save_name(manager); + saved_manager = tomoyo_get_name(manager); if (!saved_manager) return -ENOMEM; if (!is_delete) @@ -1132,12 +1134,14 @@ static int tomoyo_update_manager_entry(const char *manager, } if (!is_delete && error && tomoyo_memory_ok(entry)) { entry->manager = saved_manager; + saved_manager = NULL; entry->is_domain = is_domain; list_add_tail_rcu(&entry->list, &tomoyo_policy_manager_list); entry = NULL; error = 0; } mutex_unlock(&tomoyo_policy_lock); + tomoyo_put_name(saved_manager); kfree(entry); return error; } diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 229de1e..0b82625 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -203,7 +203,7 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, { struct tomoyo_domain_initializer_entry *entry = NULL; struct tomoyo_domain_initializer_entry *ptr; - const struct tomoyo_path_info *saved_program; + const struct tomoyo_path_info *saved_program = NULL; const struct tomoyo_path_info *saved_domainname = NULL; int error = is_delete ? -ENOENT : -ENOMEM; bool is_last_name = false; @@ -216,11 +216,11 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, is_last_name = true; else if (!tomoyo_is_correct_domain(domainname, __func__)) return -EINVAL; - saved_domainname = tomoyo_save_name(domainname); + saved_domainname = tomoyo_get_name(domainname); if (!saved_domainname) goto out; } - saved_program = tomoyo_save_name(program); + saved_program = tomoyo_get_name(program); if (!saved_program) goto out; if (!is_delete) @@ -237,7 +237,9 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, } if (!is_delete && error && tomoyo_memory_ok(entry)) { entry->domainname = saved_domainname; + saved_domainname = NULL; entry->program = saved_program; + saved_program = NULL; entry->is_not = is_not; entry->is_last_name = is_last_name; list_add_tail_rcu(&entry->list, @@ -247,6 +249,8 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, } mutex_unlock(&tomoyo_policy_lock); out: + tomoyo_put_name(saved_domainname); + tomoyo_put_name(saved_program); kfree(entry); return error; } @@ -419,7 +423,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, { struct tomoyo_domain_keeper_entry *entry = NULL; struct tomoyo_domain_keeper_entry *ptr; - const struct tomoyo_path_info *saved_domainname; + const struct tomoyo_path_info *saved_domainname = NULL; const struct tomoyo_path_info *saved_program = NULL; int error = is_delete ? -ENOENT : -ENOMEM; bool is_last_name = false; @@ -432,11 +436,11 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, if (program) { if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__)) return -EINVAL; - saved_program = tomoyo_save_name(program); + saved_program = tomoyo_get_name(program); if (!saved_program) goto out; } - saved_domainname = tomoyo_save_name(domainname); + saved_domainname = tomoyo_get_name(domainname); if (!saved_domainname) goto out; if (!is_delete) @@ -453,7 +457,9 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, } if (!is_delete && error && tomoyo_memory_ok(entry)) { entry->domainname = saved_domainname; + saved_domainname = NULL; entry->program = saved_program; + saved_program = NULL; entry->is_not = is_not; entry->is_last_name = is_last_name; list_add_tail_rcu(&entry->list, &tomoyo_domain_keeper_list); @@ -462,6 +468,8 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, } mutex_unlock(&tomoyo_policy_lock); out: + tomoyo_put_name(saved_domainname); + tomoyo_put_name(saved_program); kfree(entry); return error; } @@ -623,8 +631,8 @@ static int tomoyo_update_alias_entry(const char *original_name, if (!tomoyo_is_correct_path(original_name, 1, -1, -1, __func__) || !tomoyo_is_correct_path(aliased_name, 1, -1, -1, __func__)) return -EINVAL; /* No patterns allowed. */ - saved_original_name = tomoyo_save_name(original_name); - saved_aliased_name = tomoyo_save_name(aliased_name); + saved_original_name = tomoyo_get_name(original_name); + saved_aliased_name = tomoyo_get_name(aliased_name); if (!saved_original_name || !saved_aliased_name) goto out; if (!is_delete) @@ -640,13 +648,17 @@ static int tomoyo_update_alias_entry(const char *original_name, } if (!is_delete && error && tomoyo_memory_ok(entry)) { entry->original_name = saved_original_name; + saved_original_name = NULL; entry->aliased_name = saved_aliased_name; + saved_aliased_name = NULL; list_add_tail_rcu(&entry->list, &tomoyo_alias_list); entry = NULL; error = 0; } mutex_unlock(&tomoyo_policy_lock); out: + tomoyo_put_name(saved_original_name); + tomoyo_put_name(saved_aliased_name); kfree(entry); return error; } @@ -721,7 +733,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * if (!tomoyo_is_correct_domain(domainname, __func__)) return NULL; - saved_domainname = tomoyo_save_name(domainname); + saved_domainname = tomoyo_get_name(domainname); if (!saved_domainname) return NULL; entry = kzalloc(sizeof(*entry), GFP_KERNEL); @@ -736,6 +748,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * if (!found && tomoyo_memory_ok(entry)) { INIT_LIST_HEAD(&entry->acl_info_list); entry->domainname = saved_domainname; + saved_domainname = NULL; entry->profile = profile; list_add_tail_rcu(&entry->list, &tomoyo_domain_list); domain = entry; @@ -743,6 +756,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * found = true; } mutex_unlock(&tomoyo_policy_lock); + tomoyo_put_name(saved_domainname); kfree(entry); return found ? domain : NULL; } diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index f4a2771..a49e18c 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -222,7 +222,7 @@ static int tomoyo_update_globally_readable_entry(const char *filename, if (!tomoyo_is_correct_path(filename, 1, 0, -1, __func__)) return -EINVAL; - saved_filename = tomoyo_save_name(filename); + saved_filename = tomoyo_get_name(filename); if (!saved_filename) return -ENOMEM; if (!is_delete) @@ -237,11 +237,13 @@ static int tomoyo_update_globally_readable_entry(const char *filename, } if (!is_delete && error && tomoyo_memory_ok(entry)) { entry->filename = saved_filename; + saved_filename = NULL; list_add_tail_rcu(&entry->list, &tomoyo_globally_readable_list); entry = NULL; error = 0; } mutex_unlock(&tomoyo_policy_lock); + tomoyo_put_name(saved_filename); kfree(entry); return error; } @@ -365,7 +367,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, const struct tomoyo_path_info *saved_pattern; int error = is_delete ? -ENOENT : -ENOMEM; - saved_pattern = tomoyo_save_name(pattern); + saved_pattern = tomoyo_get_name(pattern); if (!saved_pattern) return error; if (!saved_pattern->is_patterned) @@ -382,6 +384,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, } if (!is_delete && error && tomoyo_memory_ok(entry)) { entry->pattern = saved_pattern; + saved_pattern = NULL; list_add_tail_rcu(&entry->list, &tomoyo_pattern_list); entry = NULL; error = 0; @@ -389,6 +392,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, mutex_unlock(&tomoyo_policy_lock); out: kfree(entry); + tomoyo_put_name(saved_pattern); return error; } @@ -518,7 +522,7 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__)) return -EINVAL; - saved_pattern = tomoyo_save_name(pattern); + saved_pattern = tomoyo_get_name(pattern); if (!saved_pattern) return error; if (!is_delete) @@ -533,11 +537,13 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, } if (!is_delete && error && tomoyo_memory_ok(entry)) { entry->pattern = saved_pattern; + saved_pattern = NULL; list_add_tail_rcu(&entry->list, &tomoyo_no_rewrite_list); entry = NULL; error = 0; } mutex_unlock(&tomoyo_policy_lock); + tomoyo_put_name(saved_pattern); kfree(entry); return error; } @@ -867,7 +873,7 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, return -EINVAL; if (!tomoyo_is_correct_path(filename, 0, 0, 0, __func__)) return -EINVAL; - saved_filename = tomoyo_save_name(filename); + saved_filename = tomoyo_get_name(filename); if (!saved_filename) return -ENOMEM; if (!is_delete) @@ -913,12 +919,14 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL)) entry->perm |= rw_mask; entry->filename = saved_filename; + saved_filename = NULL; list_add_tail_rcu(&entry->head.list, &domain->acl_info_list); entry = NULL; error = 0; } mutex_unlock(&tomoyo_policy_lock); kfree(entry); + tomoyo_put_name(saved_filename); return error; } @@ -952,8 +960,8 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, 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); + saved_filename1 = tomoyo_get_name(filename1); + saved_filename2 = tomoyo_get_name(filename2); if (!saved_filename1 || !saved_filename2) goto out; if (!is_delete) @@ -979,13 +987,17 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, entry->head.type = TOMOYO_TYPE_DOUBLE_PATH_ACL; entry->perm = perm; entry->filename1 = saved_filename1; + saved_filename1 = NULL; entry->filename2 = saved_filename2; + saved_filename2 = NULL; list_add_tail_rcu(&entry->head.list, &domain->acl_info_list); entry = NULL; error = 0; } mutex_unlock(&tomoyo_policy_lock); out: + tomoyo_put_name(saved_filename1); + tomoyo_put_name(saved_filename2); kfree(entry); return error; } diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 92460c7..2f7f54f 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -254,21 +254,6 @@ static unsigned int tomoyo_quota_for_savename; #define TOMOYO_MAX_HASH (1u<entry.hash && !strcmp(name, ptr->entry.name)) - goto out; + if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name)) + continue; + atomic_inc(&ptr->users); + goto out; } ptr = kzalloc(sizeof(*ptr) + len, GFP_KERNEL); allocated_len = ptr ? ksize(ptr) : 0; @@ -309,7 +296,7 @@ const struct tomoyo_path_info *tomoyo_save_name(const char *name) > tomoyo_quota_for_savename)) { kfree(ptr); printk(KERN_WARNING "ERROR: Out of memory " - "for tomoyo_save_name().\n"); + "for tomoyo_get_name().\n"); if (!tomoyo_policy_loaded) panic("MAC Initialization failed.\n"); ptr = NULL; @@ -318,6 +305,7 @@ const struct tomoyo_path_info *tomoyo_save_name(const char *name) tomoyo_allocated_memory_for_savename += allocated_len; ptr->entry.name = ((char *) ptr) + sizeof(*ptr); memmove((char *) ptr->entry.name, name, len); + atomic_set(&ptr->users, 1); tomoyo_fill_path_info(&ptr->entry); list_add_tail(&ptr->list, head); out: @@ -336,7 +324,7 @@ void __init tomoyo_realpath_init(void) for (i = 0; i < TOMOYO_MAX_HASH; i++) INIT_LIST_HEAD(&tomoyo_name_list[i]); INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list); - tomoyo_kernel_domain.domainname = tomoyo_save_name(TOMOYO_ROOT_NAME); + tomoyo_kernel_domain.domainname = tomoyo_get_name(TOMOYO_ROOT_NAME); /* * tomoyo_read_lock() is not needed because this function is * called before the first "delete" request. diff --git a/security/tomoyo/realpath.h b/security/tomoyo/realpath.h index da4f06f..b94cb51 100644 --- a/security/tomoyo/realpath.h +++ b/security/tomoyo/realpath.h @@ -43,7 +43,7 @@ bool tomoyo_memory_ok(void *ptr); * Keep the given name on the RAM. * The RAM is shared, so NEVER try to modify or kfree() the returned name. */ -const struct tomoyo_path_info *tomoyo_save_name(const char *name); +const struct tomoyo_path_info *tomoyo_get_name(const char *name); /* Check for memory usage. */ int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head); @@ -54,4 +54,23 @@ int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head); /* Initialize realpath related code. */ void __init tomoyo_realpath_init(void); +/* + * tomoyo_name_entry is a structure which is used for linking + * "struct tomoyo_path_info" into tomoyo_name_list . + */ +struct tomoyo_name_entry { + struct list_head list; + atomic_t users; + struct tomoyo_path_info entry; +}; + +static inline void tomoyo_put_name(const struct tomoyo_path_info *name) +{ + if (name) { + struct tomoyo_name_entry *ptr = + container_of(name, struct tomoyo_name_entry, entry); + atomic_dec(&ptr->users); + } +} + #endif /* !defined(_SECURITY_TOMOYO_REALPATH_H) */ -- cgit v1.1 From 76bb0895d038be7bcdb6ccfcd2dd7deb30371d6b Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Thu, 11 Feb 2010 09:42:40 +0900 Subject: TOMOYO: Merge headers. Gather structures and constants scattered around security/tomoyo/ directory. This is for preparation for adding garbage collector since garbage collector needs to know structures and constants which TOMOYO uses. Signed-off-by: Tetsuo Handa Acked-by: Serge Hallyn Signed-off-by: James Morris --- security/tomoyo/common.c | 23 --- security/tomoyo/common.h | 411 ++++++++++++++++++++++++++++++++++++++------- security/tomoyo/domain.c | 72 -------- security/tomoyo/file.c | 52 ------ security/tomoyo/realpath.c | 10 -- security/tomoyo/realpath.h | 76 --------- security/tomoyo/tomoyo.c | 2 - security/tomoyo/tomoyo.h | 102 ----------- 8 files changed, 351 insertions(+), 397 deletions(-) delete mode 100644 security/tomoyo/realpath.h delete mode 100644 security/tomoyo/tomoyo.h (limited to 'security/tomoyo') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 0c7ea51..634f744 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -13,8 +13,6 @@ #include #include #include "common.h" -#include "realpath.h" -#include "tomoyo.h" /* Lock for protecting policy. */ DEFINE_MUTEX(tomoyo_policy_lock); @@ -1040,27 +1038,6 @@ static int tomoyo_read_profile(struct tomoyo_io_buffer *head) } /* - * tomoyo_policy_manager_entry is a structure which is used for holding list of - * domainnames or programs which are permitted to modify configuration via - * /sys/kernel/security/tomoyo/ interface. - * It has following fields. - * - * (1) "list" which is linked to tomoyo_policy_manager_list . - * (2) "manager" is a domainname or a program's pathname. - * (3) "is_domain" is a bool which is true if "manager" is a domainname, false - * otherwise. - * (4) "is_deleted" is a bool which is true if marked as deleted, false - * otherwise. - */ -struct tomoyo_policy_manager_entry { - struct list_head list; - /* A path to program or a domainname. */ - const struct tomoyo_path_info *manager; - bool is_domain; /* True if manager is a domainname. */ - bool is_deleted; /* True if this entry is deleted. */ -}; - -/* * tomoyo_policy_manager_list is used for holding list of domainnames or * programs which are permitted to modify configuration via * /sys/kernel/security/tomoyo/ interface. diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 509ced9c..f6aff59 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -1,12 +1,9 @@ /* * security/tomoyo/common.h * - * Common functions for TOMOYO. - * - * Copyright (C) 2005-2009 NTT DATA CORPORATION - * - * Version: 2.2.0 2009/04/01 + * Header file for TOMOYO. * + * Copyright (C) 2005-2010 NTT DATA CORPORATION */ #ifndef _SECURITY_TOMOYO_COMMON_H @@ -22,9 +19,110 @@ #include #include #include +#include +struct linux_binprm; + +/********** Constants definitions. **********/ + +/* + * TOMOYO uses this hash only when appending a string into the string + * table. Frequency of appending strings is very low. So we don't need + * large (e.g. 64k) hash size. 256 will be sufficient. + */ +#define TOMOYO_HASH_BITS 8 +#define TOMOYO_MAX_HASH (1u<. */ +#define TOMOYO_ROOT_NAME "" +#define TOMOYO_ROOT_NAME_LEN (sizeof(TOMOYO_ROOT_NAME) - 1) + +/* Index numbers for Access Controls. */ +#define TOMOYO_MAC_FOR_FILE 0 /* domain_policy.conf */ +#define TOMOYO_MAX_ACCEPT_ENTRY 1 +#define TOMOYO_VERBOSE 2 +#define TOMOYO_MAX_CONTROL_INDEX 3 + +/* Index numbers for Access Controls. */ + +#define TOMOYO_TYPE_SINGLE_PATH_ACL 0 +#define TOMOYO_TYPE_DOUBLE_PATH_ACL 1 + +/* Index numbers for File Controls. */ + +/* + * TYPE_READ_WRITE_ACL is special. TYPE_READ_WRITE_ACL is automatically set + * if both TYPE_READ_ACL and TYPE_WRITE_ACL are set. Both TYPE_READ_ACL and + * TYPE_WRITE_ACL are automatically set if TYPE_READ_WRITE_ACL is set. + * TYPE_READ_WRITE_ACL is automatically cleared if either TYPE_READ_ACL or + * TYPE_WRITE_ACL is cleared. Both TYPE_READ_ACL and TYPE_WRITE_ACL are + * automatically cleared if TYPE_READ_WRITE_ACL is cleared. + */ + +#define TOMOYO_TYPE_READ_WRITE_ACL 0 +#define TOMOYO_TYPE_EXECUTE_ACL 1 +#define TOMOYO_TYPE_READ_ACL 2 +#define TOMOYO_TYPE_WRITE_ACL 3 +#define TOMOYO_TYPE_CREATE_ACL 4 +#define TOMOYO_TYPE_UNLINK_ACL 5 +#define TOMOYO_TYPE_MKDIR_ACL 6 +#define TOMOYO_TYPE_RMDIR_ACL 7 +#define TOMOYO_TYPE_MKFIFO_ACL 8 +#define TOMOYO_TYPE_MKSOCK_ACL 9 +#define TOMOYO_TYPE_MKBLOCK_ACL 10 +#define TOMOYO_TYPE_MKCHAR_ACL 11 +#define TOMOYO_TYPE_TRUNCATE_ACL 12 +#define TOMOYO_TYPE_SYMLINK_ACL 13 +#define TOMOYO_TYPE_REWRITE_ACL 14 +#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_TYPE_PIVOT_ROOT_ACL 2 +#define TOMOYO_MAX_DOUBLE_PATH_OPERATION 3 + +#define TOMOYO_DOMAINPOLICY 0 +#define TOMOYO_EXCEPTIONPOLICY 1 +#define TOMOYO_DOMAIN_STATUS 2 +#define TOMOYO_PROCESS_STATUS 3 +#define TOMOYO_MEMINFO 4 +#define TOMOYO_SELFDOMAIN 5 +#define TOMOYO_VERSION 6 +#define TOMOYO_PROFILE 7 +#define TOMOYO_MANAGER 8 -struct dentry; -struct vfsmount; +/********** Structure definitions. **********/ /* * tomoyo_page_buffer is a structure which is used for holding a pathname @@ -66,13 +164,14 @@ struct tomoyo_path_info { }; /* - * This is the max length of a token. - * - * A token consists of only ASCII printable characters. - * Non printable characters in a token is represented in \ooo style - * octal string. Thus, \ itself is represented as \\. + * tomoyo_name_entry is a structure which is used for linking + * "struct tomoyo_path_info" into tomoyo_name_list . */ -#define TOMOYO_MAX_PATHNAME_LEN 4000 +struct tomoyo_name_entry { + struct list_head list; + atomic_t users; + struct tomoyo_path_info entry; +}; /* * tomoyo_path_info_with_data is a structure which is used for holding a @@ -155,9 +254,6 @@ struct tomoyo_domain_info { bool transition_failed; /* Domain transition failed flag. */ }; -/* Profile number is an integer between 0 and 255. */ -#define TOMOYO_MAX_PROFILES 256 - /* * tomoyo_single_path_acl_record is a structure which is used for holding an * entry with one pathname operation (e.g. open(), mkdir()). @@ -204,29 +300,6 @@ struct tomoyo_double_path_acl_record { const struct tomoyo_path_info *filename2; }; -/* Keywords for ACLs. */ -#define TOMOYO_KEYWORD_ALIAS "alias " -#define TOMOYO_KEYWORD_ALLOW_READ "allow_read " -#define TOMOYO_KEYWORD_DELETE "delete " -#define TOMOYO_KEYWORD_DENY_REWRITE "deny_rewrite " -#define TOMOYO_KEYWORD_FILE_PATTERN "file_pattern " -#define TOMOYO_KEYWORD_INITIALIZE_DOMAIN "initialize_domain " -#define TOMOYO_KEYWORD_KEEP_DOMAIN "keep_domain " -#define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN "no_initialize_domain " -#define TOMOYO_KEYWORD_NO_KEEP_DOMAIN "no_keep_domain " -#define TOMOYO_KEYWORD_SELECT "select " -#define TOMOYO_KEYWORD_USE_PROFILE "use_profile " -#define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "ignore_global_allow_read" -/* A domain definition starts with . */ -#define TOMOYO_ROOT_NAME "" -#define TOMOYO_ROOT_NAME_LEN (sizeof(TOMOYO_ROOT_NAME) - 1) - -/* Index numbers for Access Controls. */ -#define TOMOYO_MAC_FOR_FILE 0 /* domain_policy.conf */ -#define TOMOYO_MAX_ACCEPT_ENTRY 1 -#define TOMOYO_VERBOSE 2 -#define TOMOYO_MAX_CONTROL_INDEX 3 - /* * tomoyo_io_buffer is a structure which is used for reading and modifying * configuration via /sys/kernel/security/tomoyo/ interface. @@ -285,6 +358,149 @@ struct tomoyo_io_buffer { int writebuf_size; }; +/* + * 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. + */ +struct tomoyo_globally_readable_file_entry { + struct list_head list; + const struct tomoyo_path_info *filename; + bool is_deleted; +}; + +/* + * 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. + */ +struct tomoyo_pattern_entry { + struct list_head list; + const struct tomoyo_path_info *pattern; + bool is_deleted; +}; + +/* + * 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. + */ +struct tomoyo_no_rewrite_entry { + struct list_head list; + const struct tomoyo_path_info *pattern; + bool is_deleted; +}; + +/* + * tomoyo_domain_initializer_entry is a structure which is used for holding + * "initialize_domain" and "no_initialize_domain" entries. + * It has following fields. + * + * (1) "list" which is linked to tomoyo_domain_initializer_list . + * (2) "domainname" which is "a domainname" or "the last component of a + * domainname". This field is NULL if "from" clause is not specified. + * (3) "program" which is a program's pathname. + * (4) "is_deleted" is a bool which is true if marked as deleted, false + * otherwise. + * (5) "is_not" is a bool which is true if "no_initialize_domain", false + * otherwise. + * (6) "is_last_name" is a bool which is true if "domainname" is "the last + * component of a domainname", false otherwise. + */ +struct tomoyo_domain_initializer_entry { + struct list_head list; + const struct tomoyo_path_info *domainname; /* This may be NULL */ + const struct tomoyo_path_info *program; + bool is_deleted; + bool is_not; /* True if this entry is "no_initialize_domain". */ + /* True if the domainname is tomoyo_get_last_name(). */ + bool is_last_name; +}; + +/* + * tomoyo_domain_keeper_entry is a structure which is used for holding + * "keep_domain" and "no_keep_domain" entries. + * It has following fields. + * + * (1) "list" which is linked to tomoyo_domain_keeper_list . + * (2) "domainname" which is "a domainname" or "the last component of a + * domainname". + * (3) "program" which is a program's pathname. + * This field is NULL if "from" clause is not specified. + * (4) "is_deleted" is a bool which is true if marked as deleted, false + * otherwise. + * (5) "is_not" is a bool which is true if "no_initialize_domain", false + * otherwise. + * (6) "is_last_name" is a bool which is true if "domainname" is "the last + * component of a domainname", false otherwise. + */ +struct tomoyo_domain_keeper_entry { + struct list_head list; + const struct tomoyo_path_info *domainname; + const struct tomoyo_path_info *program; /* This may be NULL */ + bool is_deleted; + bool is_not; /* True if this entry is "no_keep_domain". */ + /* True if the domainname is tomoyo_get_last_name(). */ + bool is_last_name; +}; + +/* + * tomoyo_alias_entry is a structure which is used for holding "alias" entries. + * It has following fields. + * + * (1) "list" which is linked to tomoyo_alias_list . + * (2) "original_name" which is a dereferenced pathname. + * (3) "aliased_name" which is a symlink's pathname. + * (4) "is_deleted" is a bool which is true if marked as deleted, false + * otherwise. + */ +struct tomoyo_alias_entry { + struct list_head list; + const struct tomoyo_path_info *original_name; + const struct tomoyo_path_info *aliased_name; + bool is_deleted; +}; + +/* + * tomoyo_policy_manager_entry is a structure which is used for holding list of + * domainnames or programs which are permitted to modify configuration via + * /sys/kernel/security/tomoyo/ interface. + * It has following fields. + * + * (1) "list" which is linked to tomoyo_policy_manager_list . + * (2) "manager" is a domainname or a program's pathname. + * (3) "is_domain" is a bool which is true if "manager" is a domainname, false + * otherwise. + * (4) "is_deleted" is a bool which is true if marked as deleted, false + * otherwise. + */ +struct tomoyo_policy_manager_entry { + struct list_head list; + /* A path to program or a domainname. */ + const struct tomoyo_path_info *manager; + bool is_domain; /* True if manager is a domainname. */ + bool is_deleted; /* True if this entry is deleted. */ +}; + +/********** Function prototypes. **********/ + /* Check whether the domain has too many ACL entries to hold. */ bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain); /* Transactional sprintf() for policy dump. */ @@ -367,6 +583,85 @@ void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); /* Run policy loader when /sbin/init starts. */ void tomoyo_load_policy(const char *filename); +/* Convert binary string to ascii string. */ +int tomoyo_encode(char *buffer, int buflen, const char *str); + +/* Returns realpath(3) of the given pathname but ignores chroot'ed root. */ +int tomoyo_realpath_from_path2(struct path *path, char *newname, + int newname_len); + +/* + * Returns realpath(3) of the given pathname but ignores chroot'ed root. + * These functions use kzalloc(), so the caller must call kfree() + * if these functions didn't return NULL. + */ +char *tomoyo_realpath(const char *pathname); +/* + * Same with tomoyo_realpath() except that it doesn't follow the final symlink. + */ +char *tomoyo_realpath_nofollow(const char *pathname); +/* Same with tomoyo_realpath() except that the pathname is already solved. */ +char *tomoyo_realpath_from_path(struct path *path); + +/* Check memory quota. */ +bool tomoyo_memory_ok(void *ptr); + +/* + * Keep the given name on the RAM. + * The RAM is shared, so NEVER try to modify or kfree() the returned name. + */ +const struct tomoyo_path_info *tomoyo_get_name(const char *name); + +/* Check for memory usage. */ +int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head); + +/* Set memory quota. */ +int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head); + +/* Initialize realpath related code. */ +void __init tomoyo_realpath_init(void); +int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, + const struct tomoyo_path_info *filename); +int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, + struct path *path, const int flag); +int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain, + const u8 operation, struct path *path); +int tomoyo_check_2path_perm(struct tomoyo_domain_info *domain, + const u8 operation, struct path *path1, + struct path *path2); +int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, + struct file *filp); +int tomoyo_find_next_domain(struct linux_binprm *bprm); + +/********** External variable definitions. **********/ + +/* Lock for GC. */ +extern struct srcu_struct tomoyo_ss; + +/* The list for "struct tomoyo_domain_info". */ +extern struct list_head tomoyo_domain_list; + +/* Lock for protecting policy. */ +extern struct mutex tomoyo_policy_lock; + +/* Has /sbin/init started? */ +extern bool tomoyo_policy_loaded; + +/* The kernel's domain. */ +extern struct tomoyo_domain_info tomoyo_kernel_domain; + +/********** Inlined functions. **********/ + +static inline int tomoyo_read_lock(void) +{ + return srcu_read_lock(&tomoyo_ss); +} + +static inline void tomoyo_read_unlock(int idx) +{ + srcu_read_unlock(&tomoyo_ss, idx); +} + /* strcmp() for "struct tomoyo_path_info" structure. */ static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a, const struct tomoyo_path_info *b) @@ -398,17 +693,25 @@ static inline bool tomoyo_is_invalid(const unsigned char c) return c && (c <= ' ' || c >= 127); } -/* The list for "struct tomoyo_domain_info". */ -extern struct list_head tomoyo_domain_list; - -/* Lock for protecting policy. */ -extern struct mutex tomoyo_policy_lock; +static inline void tomoyo_put_name(const struct tomoyo_path_info *name) +{ + if (name) { + struct tomoyo_name_entry *ptr = + container_of(name, struct tomoyo_name_entry, entry); + atomic_dec(&ptr->users); + } +} -/* Has /sbin/init started? */ -extern bool tomoyo_policy_loaded; +static inline struct tomoyo_domain_info *tomoyo_domain(void) +{ + return current_cred()->security; +} -/* The kernel's domain. */ -extern struct tomoyo_domain_info tomoyo_kernel_domain; +static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct + *task) +{ + return task_cred_xxx(task, security); +} /** * list_for_each_cookie - iterate over a list with cookie. @@ -428,16 +731,4 @@ extern struct tomoyo_domain_info tomoyo_kernel_domain; prefetch(pos->next), pos != (head) || ((cookie) = NULL); \ (cookie) = pos, pos = rcu_dereference(pos->next)) -extern struct srcu_struct tomoyo_ss; - -static inline int tomoyo_read_lock(void) -{ - return srcu_read_lock(&tomoyo_ss); -} - -static inline void tomoyo_read_unlock(int idx) -{ - srcu_read_unlock(&tomoyo_ss, idx); -} - #endif /* !defined(_SECURITY_TOMOYO_COMMON_H) */ diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 0b82625..d60b8a6 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -10,8 +10,6 @@ */ #include "common.h" -#include "tomoyo.h" -#include "realpath.h" #include /* Variables definitions.*/ @@ -59,76 +57,6 @@ struct tomoyo_domain_info tomoyo_kernel_domain; */ LIST_HEAD(tomoyo_domain_list); -/* - * tomoyo_domain_initializer_entry is a structure which is used for holding - * "initialize_domain" and "no_initialize_domain" entries. - * It has following fields. - * - * (1) "list" which is linked to tomoyo_domain_initializer_list . - * (2) "domainname" which is "a domainname" or "the last component of a - * domainname". This field is NULL if "from" clause is not specified. - * (3) "program" which is a program's pathname. - * (4) "is_deleted" is a bool which is true if marked as deleted, false - * otherwise. - * (5) "is_not" is a bool which is true if "no_initialize_domain", false - * otherwise. - * (6) "is_last_name" is a bool which is true if "domainname" is "the last - * component of a domainname", false otherwise. - */ -struct tomoyo_domain_initializer_entry { - struct list_head list; - const struct tomoyo_path_info *domainname; /* This may be NULL */ - const struct tomoyo_path_info *program; - bool is_deleted; - bool is_not; /* True if this entry is "no_initialize_domain". */ - /* True if the domainname is tomoyo_get_last_name(). */ - bool is_last_name; -}; - -/* - * tomoyo_domain_keeper_entry is a structure which is used for holding - * "keep_domain" and "no_keep_domain" entries. - * It has following fields. - * - * (1) "list" which is linked to tomoyo_domain_keeper_list . - * (2) "domainname" which is "a domainname" or "the last component of a - * domainname". - * (3) "program" which is a program's pathname. - * This field is NULL if "from" clause is not specified. - * (4) "is_deleted" is a bool which is true if marked as deleted, false - * otherwise. - * (5) "is_not" is a bool which is true if "no_initialize_domain", false - * otherwise. - * (6) "is_last_name" is a bool which is true if "domainname" is "the last - * component of a domainname", false otherwise. - */ -struct tomoyo_domain_keeper_entry { - struct list_head list; - const struct tomoyo_path_info *domainname; - const struct tomoyo_path_info *program; /* This may be NULL */ - bool is_deleted; - bool is_not; /* True if this entry is "no_keep_domain". */ - /* True if the domainname is tomoyo_get_last_name(). */ - bool is_last_name; -}; - -/* - * tomoyo_alias_entry is a structure which is used for holding "alias" entries. - * It has following fields. - * - * (1) "list" which is linked to tomoyo_alias_list . - * (2) "original_name" which is a dereferenced pathname. - * (3) "aliased_name" which is a symlink's pathname. - * (4) "is_deleted" is a bool which is true if marked as deleted, false - * otherwise. - */ -struct tomoyo_alias_entry { - struct list_head list; - const struct tomoyo_path_info *original_name; - const struct tomoyo_path_info *aliased_name; - bool is_deleted; -}; - /** * tomoyo_get_last_name - Get last component of a domainname. * diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index a49e18c..c69dd39 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -10,58 +10,6 @@ */ #include "common.h" -#include "tomoyo.h" -#include "realpath.h" - -/* - * 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. - */ -struct tomoyo_globally_readable_file_entry { - struct list_head list; - const struct tomoyo_path_info *filename; - bool is_deleted; -}; - -/* - * 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. - */ -struct tomoyo_pattern_entry { - struct list_head list; - const struct tomoyo_path_info *pattern; - bool is_deleted; -}; - -/* - * 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. - */ -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] = { diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 2f7f54f..9557168 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -15,9 +15,7 @@ #include #include #include - #include "common.h" -#include "realpath.h" /** * tomoyo_encode: Convert binary string to ascii string. @@ -246,14 +244,6 @@ static unsigned int tomoyo_allocated_memory_for_savename; static unsigned int tomoyo_quota_for_savename; /* - * TOMOYO uses this hash only when appending a string into the string - * table. Frequency of appending strings is very low. So we don't need - * large (e.g. 64k) hash size. 256 will be sufficient. - */ -#define TOMOYO_HASH_BITS 8 -#define TOMOYO_MAX_HASH (1u<users); - } -} - -#endif /* !defined(_SECURITY_TOMOYO_REALPATH_H) */ diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 714daa3..8a0988d 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -11,8 +11,6 @@ #include #include "common.h" -#include "tomoyo.h" -#include "realpath.h" static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp) { diff --git a/security/tomoyo/tomoyo.h b/security/tomoyo/tomoyo.h deleted file mode 100644 index bf3986a..0000000 --- a/security/tomoyo/tomoyo.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * security/tomoyo/tomoyo.h - * - * Implementation of the Domain-Based Mandatory Access Control. - * - * Copyright (C) 2005-2009 NTT DATA CORPORATION - * - * Version: 2.2.0 2009/04/01 - * - */ - -#ifndef _SECURITY_TOMOYO_TOMOYO_H -#define _SECURITY_TOMOYO_TOMOYO_H - -struct tomoyo_path_info; -struct path; -struct inode; -struct linux_binprm; -struct pt_regs; - -int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, - const struct tomoyo_path_info *filename); -int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, - struct path *path, const int flag); -int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain, - const u8 operation, struct path *path); -int tomoyo_check_2path_perm(struct tomoyo_domain_info *domain, - const u8 operation, struct path *path1, - struct path *path2); -int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, - struct file *filp); -int tomoyo_find_next_domain(struct linux_binprm *bprm); - -/* Index numbers for Access Controls. */ - -#define TOMOYO_TYPE_SINGLE_PATH_ACL 0 -#define TOMOYO_TYPE_DOUBLE_PATH_ACL 1 - -/* Index numbers for File Controls. */ - -/* - * TYPE_READ_WRITE_ACL is special. TYPE_READ_WRITE_ACL is automatically set - * if both TYPE_READ_ACL and TYPE_WRITE_ACL are set. Both TYPE_READ_ACL and - * TYPE_WRITE_ACL are automatically set if TYPE_READ_WRITE_ACL is set. - * TYPE_READ_WRITE_ACL is automatically cleared if either TYPE_READ_ACL or - * TYPE_WRITE_ACL is cleared. Both TYPE_READ_ACL and TYPE_WRITE_ACL are - * automatically cleared if TYPE_READ_WRITE_ACL is cleared. - */ - -#define TOMOYO_TYPE_READ_WRITE_ACL 0 -#define TOMOYO_TYPE_EXECUTE_ACL 1 -#define TOMOYO_TYPE_READ_ACL 2 -#define TOMOYO_TYPE_WRITE_ACL 3 -#define TOMOYO_TYPE_CREATE_ACL 4 -#define TOMOYO_TYPE_UNLINK_ACL 5 -#define TOMOYO_TYPE_MKDIR_ACL 6 -#define TOMOYO_TYPE_RMDIR_ACL 7 -#define TOMOYO_TYPE_MKFIFO_ACL 8 -#define TOMOYO_TYPE_MKSOCK_ACL 9 -#define TOMOYO_TYPE_MKBLOCK_ACL 10 -#define TOMOYO_TYPE_MKCHAR_ACL 11 -#define TOMOYO_TYPE_TRUNCATE_ACL 12 -#define TOMOYO_TYPE_SYMLINK_ACL 13 -#define TOMOYO_TYPE_REWRITE_ACL 14 -#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_TYPE_PIVOT_ROOT_ACL 2 -#define TOMOYO_MAX_DOUBLE_PATH_OPERATION 3 - -#define TOMOYO_DOMAINPOLICY 0 -#define TOMOYO_EXCEPTIONPOLICY 1 -#define TOMOYO_DOMAIN_STATUS 2 -#define TOMOYO_PROCESS_STATUS 3 -#define TOMOYO_MEMINFO 4 -#define TOMOYO_SELFDOMAIN 5 -#define TOMOYO_VERSION 6 -#define TOMOYO_PROFILE 7 -#define TOMOYO_MANAGER 8 - -extern struct tomoyo_domain_info tomoyo_kernel_domain; - -static inline struct tomoyo_domain_info *tomoyo_domain(void) -{ - return current_cred()->security; -} - -static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct - *task) -{ - return task_cred_xxx(task, security); -} - -#endif /* !defined(_SECURITY_TOMOYO_TOMOYO_H) */ -- cgit v1.1 From ec8e6a4e062e2edebef91e930c20572c9f4c0dda Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Thu, 11 Feb 2010 09:43:20 +0900 Subject: TOMOYO: Add refcounter on domain structure. Add refcounter to "struct tomoyo_domain_info" since garbage collector needs to determine whether this struct is referred by "struct cred"->security or not. Signed-off-by: Tetsuo Handa Acked-by: Serge Hallyn Signed-off-by: James Morris --- security/tomoyo/common.h | 5 +++++ security/tomoyo/domain.c | 2 ++ security/tomoyo/tomoyo.c | 37 +++++++++++++++++++++---------------- 3 files changed, 28 insertions(+), 16 deletions(-) (limited to 'security/tomoyo') diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index f6aff59..521b4b5 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -234,6 +234,10 @@ struct tomoyo_acl_info { * name of the domain to be created was too long or it could not allocate * memory. If set to true, more than one process continued execve() * without domain transition. + * (9) "users" is an atomic_t that holds how many "struct cred"->security + * are referring this "struct tomoyo_domain_info". If is_deleted == true + * and users == 0, this struct will be kfree()d upon next garbage + * collection. * * A domain's lifecycle is an analogy of files on / directory. * Multiple domains with the same domainname cannot be created (as with @@ -252,6 +256,7 @@ struct tomoyo_domain_info { bool quota_warned; /* Quota warnning flag. */ bool ignore_global_allow_read; /* Ignore "allow_read" flag. */ bool transition_failed; /* Domain transition failed flag. */ + atomic_t users; /* Number of referring credentials. */ }; /* diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index d60b8a6..6f74b30 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -817,6 +817,8 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) out: if (!domain) domain = old_domain; + /* Update reference count on "struct tomoyo_domain_info". */ + atomic_inc(&domain->users); bprm->cred->security = domain; kfree(real_program_name); kfree(symlink_program_name); diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 8a0988d..87e82bf 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -21,21 +21,23 @@ static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp) static int tomoyo_cred_prepare(struct cred *new, const struct cred *old, gfp_t gfp) { - /* - * Since "struct tomoyo_domain_info *" is a sharable pointer, - * we don't need to duplicate. - */ - new->security = old->security; + struct tomoyo_domain_info *domain = old->security; + new->security = domain; + if (domain) + atomic_inc(&domain->users); return 0; } static void tomoyo_cred_transfer(struct cred *new, const struct cred *old) { - /* - * Since "struct tomoyo_domain_info *" is a sharable pointer, - * we don't need to duplicate. - */ - new->security = old->security; + tomoyo_cred_prepare(new, old, 0); +} + +static void tomoyo_cred_free(struct cred *cred) +{ + struct tomoyo_domain_info *domain = cred->security; + if (domain) + atomic_dec(&domain->users); } static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) @@ -59,6 +61,14 @@ static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) if (!tomoyo_policy_loaded) tomoyo_load_policy(bprm->filename); /* + * Release reference to "struct tomoyo_domain_info" stored inside + * "bprm->cred->security". New reference to "struct tomoyo_domain_info" + * stored inside "bprm->cred->security" will be acquired later inside + * tomoyo_find_next_domain(). + */ + atomic_dec(&((struct tomoyo_domain_info *) + bprm->cred->security)->users); + /* * Tell tomoyo_bprm_check_security() is called for the first time of an * execve operation. */ @@ -75,12 +85,6 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm) * using current domain. */ if (!domain) { - /* - * We will need to protect whole execve() operation when GC - * starts kfree()ing "struct tomoyo_domain_info" because - * bprm->cred->security points to "struct tomoyo_domain_info" - * but "struct tomoyo_domain_info" does not have a refcounter. - */ const int idx = tomoyo_read_lock(); const int err = tomoyo_find_next_domain(bprm); tomoyo_read_unlock(idx); @@ -265,6 +269,7 @@ static struct security_operations tomoyo_security_ops = { .cred_alloc_blank = tomoyo_cred_alloc_blank, .cred_prepare = tomoyo_cred_prepare, .cred_transfer = tomoyo_cred_transfer, + .cred_free = tomoyo_cred_free, .bprm_set_creds = tomoyo_bprm_set_creds, .bprm_check_security = tomoyo_bprm_check_security, .file_fcntl = tomoyo_file_fcntl, -- cgit v1.1 From 847b173ea3d6f50936823d07f2245059bf44713b Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Thu, 11 Feb 2010 09:43:54 +0900 Subject: TOMOYO: Add garbage collector. This patch adds garbage collector support to TOMOYO. Elements are protected by "struct srcu_struct tomoyo_ss". Signed-off-by: Tetsuo Handa Acked-by: Serge Hallyn Signed-off-by: James Morris --- security/tomoyo/Makefile | 2 +- security/tomoyo/common.c | 5 +- security/tomoyo/common.h | 15 ++ security/tomoyo/domain.c | 6 +- security/tomoyo/file.c | 6 +- security/tomoyo/gc.c | 370 +++++++++++++++++++++++++++++++++++++++++++++ security/tomoyo/realpath.c | 86 +++++------ 7 files changed, 436 insertions(+), 54 deletions(-) create mode 100644 security/tomoyo/gc.c (limited to 'security/tomoyo') diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile index 10ccd68..60a9e20 100644 --- a/security/tomoyo/Makefile +++ b/security/tomoyo/Makefile @@ -1 +1 @@ -obj-y = common.o realpath.o tomoyo.o domain.o file.o +obj-y = common.o realpath.o tomoyo.o domain.o file.o gc.o diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 634f744..3a36b56 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -1067,7 +1067,7 @@ static int tomoyo_read_profile(struct tomoyo_io_buffer *head) * * # cat /sys/kernel/security/tomoyo/manager */ -static LIST_HEAD(tomoyo_policy_manager_list); +LIST_HEAD(tomoyo_policy_manager_list); /** * tomoyo_update_manager_entry - Add a manager entry. @@ -2109,6 +2109,7 @@ static int tomoyo_write_control(struct file *file, const char __user *buffer, static int tomoyo_close_control(struct file *file) { struct tomoyo_io_buffer *head = file->private_data; + const bool is_write = !!head->write_buf; tomoyo_read_unlock(head->reader_idx); /* Release memory used for policy I/O. */ @@ -2119,6 +2120,8 @@ static int tomoyo_close_control(struct file *file) kfree(head); head = NULL; file->private_data = NULL; + if (is_write) + tomoyo_run_gc(); return 0; } diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 521b4b5..1c8c97a 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -638,6 +638,11 @@ int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, struct file *filp); int tomoyo_find_next_domain(struct linux_binprm *bprm); +/* Run garbage collector. */ +void tomoyo_run_gc(void); + +void tomoyo_memory_free(void *ptr); + /********** External variable definitions. **********/ /* Lock for GC. */ @@ -646,6 +651,16 @@ extern struct srcu_struct tomoyo_ss; /* The list for "struct tomoyo_domain_info". */ extern struct list_head tomoyo_domain_list; +extern struct list_head tomoyo_domain_initializer_list; +extern struct list_head tomoyo_domain_keeper_list; +extern struct list_head tomoyo_alias_list; +extern struct list_head tomoyo_globally_readable_list; +extern struct list_head tomoyo_pattern_list; +extern struct list_head tomoyo_no_rewrite_list; +extern struct list_head tomoyo_policy_manager_list; +extern struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; +extern struct mutex tomoyo_name_list_lock; + /* Lock for protecting policy. */ extern struct mutex tomoyo_policy_lock; diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 6f74b30..74cd0f5 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -110,7 +110,7 @@ const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain) * will cause "/usr/sbin/httpd" to belong to " /usr/sbin/httpd" domain * unless executed from " /etc/rc.d/init.d/httpd" domain. */ -static LIST_HEAD(tomoyo_domain_initializer_list); +LIST_HEAD(tomoyo_domain_initializer_list); /** * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list. @@ -330,7 +330,7 @@ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * * " /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain, unless * explicitly specified by "initialize_domain". */ -static LIST_HEAD(tomoyo_domain_keeper_list); +LIST_HEAD(tomoyo_domain_keeper_list); /** * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list. @@ -533,7 +533,7 @@ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, * /bin/busybox and domainname which the current process will belong to after * execve() succeeds is calculated using /bin/cat rather than /bin/busybox . */ -static LIST_HEAD(tomoyo_alias_list); +LIST_HEAD(tomoyo_alias_list); /** * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list. diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index c69dd39..10ee7ce 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -148,7 +148,7 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, * given "allow_read /lib/libc-2.5.so" to the domain which current process * belongs to. */ -static LIST_HEAD(tomoyo_globally_readable_list); +LIST_HEAD(tomoyo_globally_readable_list); /** * tomoyo_update_globally_readable_entry - Update "struct tomoyo_globally_readable_file_entry" list. @@ -295,7 +295,7 @@ bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head) * which pretends as if /proc/self/ is not a symlink; so that we can forbid * current process from accessing other process's information. */ -static LIST_HEAD(tomoyo_pattern_list); +LIST_HEAD(tomoyo_pattern_list); /** * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list. @@ -448,7 +448,7 @@ bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head) * " (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. */ -static LIST_HEAD(tomoyo_no_rewrite_list); +LIST_HEAD(tomoyo_no_rewrite_list); /** * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list. diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c new file mode 100644 index 0000000..ee15da3 --- /dev/null +++ b/security/tomoyo/gc.c @@ -0,0 +1,370 @@ +/* + * security/tomoyo/gc.c + * + * Implementation of the Domain-Based Mandatory Access Control. + * + * Copyright (C) 2005-2010 NTT DATA CORPORATION + * + */ + +#include "common.h" +#include + +enum tomoyo_gc_id { + TOMOYO_ID_DOMAIN_INITIALIZER, + TOMOYO_ID_DOMAIN_KEEPER, + TOMOYO_ID_ALIAS, + TOMOYO_ID_GLOBALLY_READABLE, + TOMOYO_ID_PATTERN, + TOMOYO_ID_NO_REWRITE, + TOMOYO_ID_MANAGER, + TOMOYO_ID_NAME, + TOMOYO_ID_ACL, + TOMOYO_ID_DOMAIN +}; + +struct tomoyo_gc_entry { + struct list_head list; + int type; + void *element; +}; +static LIST_HEAD(tomoyo_gc_queue); +static DEFINE_MUTEX(tomoyo_gc_mutex); + +/* Caller holds tomoyo_policy_lock mutex. */ +static bool tomoyo_add_to_gc(const int type, void *element) +{ + struct tomoyo_gc_entry *entry = kzalloc(sizeof(*entry), GFP_ATOMIC); + if (!entry) + return false; + entry->type = type; + entry->element = element; + list_add(&entry->list, &tomoyo_gc_queue); + return true; +} + +static void tomoyo_del_allow_read +(struct tomoyo_globally_readable_file_entry *ptr) +{ + tomoyo_put_name(ptr->filename); +} + +static void tomoyo_del_file_pattern(struct tomoyo_pattern_entry *ptr) +{ + tomoyo_put_name(ptr->pattern); +} + +static void tomoyo_del_no_rewrite(struct tomoyo_no_rewrite_entry *ptr) +{ + tomoyo_put_name(ptr->pattern); +} + +static void tomoyo_del_domain_initializer +(struct tomoyo_domain_initializer_entry *ptr) +{ + tomoyo_put_name(ptr->domainname); + tomoyo_put_name(ptr->program); +} + +static void tomoyo_del_domain_keeper(struct tomoyo_domain_keeper_entry *ptr) +{ + tomoyo_put_name(ptr->domainname); + tomoyo_put_name(ptr->program); +} + +static void tomoyo_del_alias(struct tomoyo_alias_entry *ptr) +{ + tomoyo_put_name(ptr->original_name); + tomoyo_put_name(ptr->aliased_name); +} + +static void tomoyo_del_manager(struct tomoyo_policy_manager_entry *ptr) +{ + tomoyo_put_name(ptr->manager); +} + +static void tomoyo_del_acl(struct tomoyo_acl_info *acl) +{ + switch (acl->type) { + case TOMOYO_TYPE_SINGLE_PATH_ACL: + { + struct tomoyo_single_path_acl_record *entry + = container_of(acl, typeof(*entry), head); + tomoyo_put_name(entry->filename); + } + break; + case TOMOYO_TYPE_DOUBLE_PATH_ACL: + { + struct tomoyo_double_path_acl_record *entry + = container_of(acl, typeof(*entry), head); + tomoyo_put_name(entry->filename1); + tomoyo_put_name(entry->filename2); + } + break; + default: + printk(KERN_WARNING "Unknown type\n"); + break; + } +} + +static bool tomoyo_del_domain(struct tomoyo_domain_info *domain) +{ + struct tomoyo_acl_info *acl; + struct tomoyo_acl_info *tmp; + /* + * Since we don't protect whole execve() operation using SRCU, + * we need to recheck domain->users at this point. + * + * (1) Reader starts SRCU section upon execve(). + * (2) Reader traverses tomoyo_domain_list and finds this domain. + * (3) Writer marks this domain as deleted. + * (4) Garbage collector removes this domain from tomoyo_domain_list + * because this domain is marked as deleted and used by nobody. + * (5) Reader saves reference to this domain into + * "struct linux_binprm"->cred->security . + * (6) Reader finishes SRCU section, although execve() operation has + * not finished yet. + * (7) Garbage collector waits for SRCU synchronization. + * (8) Garbage collector kfree() this domain because this domain is + * used by nobody. + * (9) Reader finishes execve() operation and restores this domain from + * "struct linux_binprm"->cred->security. + * + * By updating domain->users at (5), we can solve this race problem + * by rechecking domain->users at (8). + */ + if (atomic_read(&domain->users)) + return false; + list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) { + tomoyo_del_acl(acl); + tomoyo_memory_free(acl); + } + tomoyo_put_name(domain->domainname); + return true; +} + + +static void tomoyo_del_name(const struct tomoyo_name_entry *ptr) +{ +} + +static void tomoyo_collect_entry(void) +{ + mutex_lock(&tomoyo_policy_lock); + { + struct tomoyo_globally_readable_file_entry *ptr; + list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, + list) { + if (!ptr->is_deleted) + continue; + if (tomoyo_add_to_gc(TOMOYO_ID_GLOBALLY_READABLE, ptr)) + list_del_rcu(&ptr->list); + else + break; + } + } + { + struct tomoyo_pattern_entry *ptr; + list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { + if (!ptr->is_deleted) + continue; + if (tomoyo_add_to_gc(TOMOYO_ID_PATTERN, ptr)) + list_del_rcu(&ptr->list); + else + break; + } + } + { + struct tomoyo_no_rewrite_entry *ptr; + list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { + if (!ptr->is_deleted) + continue; + if (tomoyo_add_to_gc(TOMOYO_ID_NO_REWRITE, ptr)) + list_del_rcu(&ptr->list); + else + break; + } + } + { + struct tomoyo_domain_initializer_entry *ptr; + list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, + list) { + if (!ptr->is_deleted) + continue; + if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_INITIALIZER, ptr)) + list_del_rcu(&ptr->list); + else + break; + } + } + { + struct tomoyo_domain_keeper_entry *ptr; + list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { + if (!ptr->is_deleted) + continue; + if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_KEEPER, ptr)) + list_del_rcu(&ptr->list); + else + break; + } + } + { + struct tomoyo_alias_entry *ptr; + list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { + if (!ptr->is_deleted) + continue; + if (tomoyo_add_to_gc(TOMOYO_ID_ALIAS, ptr)) + list_del_rcu(&ptr->list); + else + break; + } + } + { + struct tomoyo_policy_manager_entry *ptr; + list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, + list) { + if (!ptr->is_deleted) + continue; + if (tomoyo_add_to_gc(TOMOYO_ID_MANAGER, ptr)) + list_del_rcu(&ptr->list); + else + break; + } + } + { + struct tomoyo_domain_info *domain; + list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { + struct tomoyo_acl_info *acl; + list_for_each_entry_rcu(acl, &domain->acl_info_list, + list) { + switch (acl->type) { + case TOMOYO_TYPE_SINGLE_PATH_ACL: + if (container_of(acl, + struct tomoyo_single_path_acl_record, + head)->perm || + container_of(acl, + struct tomoyo_single_path_acl_record, + head)->perm_high) + continue; + break; + case TOMOYO_TYPE_DOUBLE_PATH_ACL: + if (container_of(acl, + struct tomoyo_double_path_acl_record, + head)->perm) + continue; + break; + default: + continue; + } + if (tomoyo_add_to_gc(TOMOYO_ID_ACL, acl)) + list_del_rcu(&acl->list); + else + break; + } + if (!domain->is_deleted || atomic_read(&domain->users)) + continue; + /* + * Nobody is referring this domain. But somebody may + * refer this domain after successful execve(). + * We recheck domain->users after SRCU synchronization. + */ + if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, domain)) + list_del_rcu(&domain->list); + else + break; + } + } + mutex_unlock(&tomoyo_policy_lock); + mutex_lock(&tomoyo_name_list_lock); + { + int i; + for (i = 0; i < TOMOYO_MAX_HASH; i++) { + struct tomoyo_name_entry *ptr; + list_for_each_entry_rcu(ptr, &tomoyo_name_list[i], + list) { + if (atomic_read(&ptr->users)) + continue; + if (tomoyo_add_to_gc(TOMOYO_ID_NAME, ptr)) + list_del_rcu(&ptr->list); + else { + i = TOMOYO_MAX_HASH; + break; + } + } + } + } + mutex_unlock(&tomoyo_name_list_lock); +} + +static void tomoyo_kfree_entry(void) +{ + struct tomoyo_gc_entry *p; + struct tomoyo_gc_entry *tmp; + + list_for_each_entry_safe(p, tmp, &tomoyo_gc_queue, list) { + switch (p->type) { + case TOMOYO_ID_DOMAIN_INITIALIZER: + tomoyo_del_domain_initializer(p->element); + break; + case TOMOYO_ID_DOMAIN_KEEPER: + tomoyo_del_domain_keeper(p->element); + break; + case TOMOYO_ID_ALIAS: + tomoyo_del_alias(p->element); + break; + case TOMOYO_ID_GLOBALLY_READABLE: + tomoyo_del_allow_read(p->element); + break; + case TOMOYO_ID_PATTERN: + tomoyo_del_file_pattern(p->element); + break; + case TOMOYO_ID_NO_REWRITE: + tomoyo_del_no_rewrite(p->element); + break; + case TOMOYO_ID_MANAGER: + tomoyo_del_manager(p->element); + break; + case TOMOYO_ID_NAME: + tomoyo_del_name(p->element); + break; + case TOMOYO_ID_ACL: + tomoyo_del_acl(p->element); + break; + case TOMOYO_ID_DOMAIN: + if (!tomoyo_del_domain(p->element)) + continue; + break; + default: + printk(KERN_WARNING "Unknown type\n"); + break; + } + tomoyo_memory_free(p->element); + list_del(&p->list); + kfree(p); + } +} + +static int tomoyo_gc_thread(void *unused) +{ + daemonize("GC for TOMOYO"); + if (mutex_trylock(&tomoyo_gc_mutex)) { + int i; + for (i = 0; i < 10; i++) { + tomoyo_collect_entry(); + if (list_empty(&tomoyo_gc_queue)) + break; + synchronize_srcu(&tomoyo_ss); + tomoyo_kfree_entry(); + } + mutex_unlock(&tomoyo_gc_mutex); + } + do_exit(0); +} + +void tomoyo_run_gc(void) +{ + struct task_struct *task = kthread_create(tomoyo_gc_thread, NULL, + "GC for TOMOYO"); + if (!IS_ERR(task)) + wake_up_process(task); +} diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 9557168..c00df45 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -205,9 +205,9 @@ char *tomoyo_realpath_nofollow(const char *pathname) } /* Memory allocated for non-string data. */ -static unsigned int tomoyo_allocated_memory_for_elements; -/* Quota for holding non-string data. */ -static unsigned int tomoyo_quota_for_elements; +static atomic_t tomoyo_policy_memory_size; +/* Quota for holding policy. */ +static unsigned int tomoyo_quota_for_policy; /** * tomoyo_memory_ok - Check memory quota. @@ -222,26 +222,30 @@ static unsigned int tomoyo_quota_for_elements; bool tomoyo_memory_ok(void *ptr) { int allocated_len = ptr ? ksize(ptr) : 0; - bool result = false; - if (!ptr || (tomoyo_quota_for_elements && - tomoyo_allocated_memory_for_elements - + allocated_len > tomoyo_quota_for_elements)) { - printk(KERN_WARNING "ERROR: Out of memory " - "for tomoyo_alloc_element().\n"); - if (!tomoyo_policy_loaded) - panic("MAC Initialization failed.\n"); - } else { - result = true; - tomoyo_allocated_memory_for_elements += allocated_len; + atomic_add(allocated_len, &tomoyo_policy_memory_size); + if (ptr && (!tomoyo_quota_for_policy || + atomic_read(&tomoyo_policy_memory_size) + <= tomoyo_quota_for_policy)) { memset(ptr, 0, allocated_len); + return true; } - return result; + printk(KERN_WARNING "ERROR: Out of memory " + "for tomoyo_alloc_element().\n"); + if (!tomoyo_policy_loaded) + panic("MAC Initialization failed.\n"); + return false; } -/* Memory allocated for string data in bytes. */ -static unsigned int tomoyo_allocated_memory_for_savename; -/* Quota for holding string data in bytes. */ -static unsigned int tomoyo_quota_for_savename; +/** + * tomoyo_memory_free - Free memory for elements. + * + * @ptr: Pointer to allocated memory. + */ +void tomoyo_memory_free(void *ptr) +{ + atomic_sub(ksize(ptr), &tomoyo_policy_memory_size); + kfree(ptr); +} /* * tomoyo_name_list is used for holding string data used by TOMOYO. @@ -249,7 +253,9 @@ static unsigned int tomoyo_quota_for_savename; * "/lib/libc-2.5.so"), TOMOYO shares string data in the form of * "const struct tomoyo_path_info *". */ -static struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; +struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; +/* Lock for protecting tomoyo_name_list . */ +DEFINE_MUTEX(tomoyo_name_list_lock); /** * tomoyo_get_name - Allocate permanent memory for string data. @@ -260,7 +266,6 @@ static struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; */ const struct tomoyo_path_info *tomoyo_get_name(const char *name) { - static DEFINE_MUTEX(lock); struct tomoyo_name_entry *ptr; unsigned int hash; int len; @@ -272,7 +277,7 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name) len = strlen(name) + 1; hash = full_name_hash((const unsigned char *) name, len - 1); head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)]; - mutex_lock(&lock); + mutex_lock(&tomoyo_name_list_lock); list_for_each_entry(ptr, head, list) { if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name)) continue; @@ -281,9 +286,9 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name) } ptr = kzalloc(sizeof(*ptr) + len, GFP_KERNEL); allocated_len = ptr ? ksize(ptr) : 0; - if (!ptr || (tomoyo_quota_for_savename && - tomoyo_allocated_memory_for_savename + allocated_len - > tomoyo_quota_for_savename)) { + if (!ptr || (tomoyo_quota_for_policy && + atomic_read(&tomoyo_policy_memory_size) + allocated_len + > tomoyo_quota_for_policy)) { kfree(ptr); printk(KERN_WARNING "ERROR: Out of memory " "for tomoyo_get_name().\n"); @@ -292,14 +297,14 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name) ptr = NULL; goto out; } - tomoyo_allocated_memory_for_savename += allocated_len; + atomic_add(allocated_len, &tomoyo_policy_memory_size); ptr->entry.name = ((char *) ptr) + sizeof(*ptr); memmove((char *) ptr->entry.name, name, len); atomic_set(&ptr->users, 1); tomoyo_fill_path_info(&ptr->entry); list_add_tail(&ptr->list, head); out: - mutex_unlock(&lock); + mutex_unlock(&tomoyo_name_list_lock); return ptr ? &ptr->entry : NULL; } @@ -334,28 +339,19 @@ void __init tomoyo_realpath_init(void) int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head) { if (!head->read_eof) { - const unsigned int shared - = tomoyo_allocated_memory_for_savename; - const unsigned int private - = tomoyo_allocated_memory_for_elements; + const unsigned int policy + = atomic_read(&tomoyo_policy_memory_size); char buffer[64]; memset(buffer, 0, sizeof(buffer)); - if (tomoyo_quota_for_savename) - snprintf(buffer, sizeof(buffer) - 1, - " (Quota: %10u)", - tomoyo_quota_for_savename); - else - buffer[0] = '\0'; - tomoyo_io_printf(head, "Shared: %10u%s\n", shared, buffer); - if (tomoyo_quota_for_elements) + if (tomoyo_quota_for_policy) snprintf(buffer, sizeof(buffer) - 1, " (Quota: %10u)", - tomoyo_quota_for_elements); + tomoyo_quota_for_policy); else buffer[0] = '\0'; - tomoyo_io_printf(head, "Private: %10u%s\n", private, buffer); - tomoyo_io_printf(head, "Total: %10u\n", shared + private); + tomoyo_io_printf(head, "Policy: %10u%s\n", policy, buffer); + tomoyo_io_printf(head, "Total: %10u\n", policy); head->read_eof = true; } return 0; @@ -373,9 +369,7 @@ int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head) char *data = head->write_buf; unsigned int size; - if (sscanf(data, "Shared: %u", &size) == 1) - tomoyo_quota_for_savename = size; - else if (sscanf(data, "Private: %u", &size) == 1) - tomoyo_quota_for_elements = size; + if (sscanf(data, "Policy: %u", &size) == 1) + tomoyo_quota_for_policy = size; return 0; } -- cgit v1.1 From 084da356f6e55ce42f1d2739178502023908c107 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Mon, 15 Feb 2010 15:10:39 +0900 Subject: TOMOYO: Use enum for index numbers. Use enum to declare index numbers. Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/common.h | 99 ++++++++++++++++++++++++++---------------------- 1 file changed, 54 insertions(+), 45 deletions(-) (limited to 'security/tomoyo') diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 1c8c97a..3727296 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -62,15 +62,18 @@ struct linux_binprm; #define TOMOYO_ROOT_NAME_LEN (sizeof(TOMOYO_ROOT_NAME) - 1) /* Index numbers for Access Controls. */ -#define TOMOYO_MAC_FOR_FILE 0 /* domain_policy.conf */ -#define TOMOYO_MAX_ACCEPT_ENTRY 1 -#define TOMOYO_VERBOSE 2 -#define TOMOYO_MAX_CONTROL_INDEX 3 +enum tomoyo_mac_index { + TOMOYO_MAC_FOR_FILE, /* domain_policy.conf */ + TOMOYO_MAX_ACCEPT_ENTRY, + TOMOYO_VERBOSE, + TOMOYO_MAX_CONTROL_INDEX +}; /* Index numbers for Access Controls. */ - -#define TOMOYO_TYPE_SINGLE_PATH_ACL 0 -#define TOMOYO_TYPE_DOUBLE_PATH_ACL 1 +enum tomoyo_acl_entry_type_index { + TOMOYO_TYPE_SINGLE_PATH_ACL, + TOMOYO_TYPE_DOUBLE_PATH_ACL, +}; /* Index numbers for File Controls. */ @@ -83,44 +86,50 @@ struct linux_binprm; * automatically cleared if TYPE_READ_WRITE_ACL is cleared. */ -#define TOMOYO_TYPE_READ_WRITE_ACL 0 -#define TOMOYO_TYPE_EXECUTE_ACL 1 -#define TOMOYO_TYPE_READ_ACL 2 -#define TOMOYO_TYPE_WRITE_ACL 3 -#define TOMOYO_TYPE_CREATE_ACL 4 -#define TOMOYO_TYPE_UNLINK_ACL 5 -#define TOMOYO_TYPE_MKDIR_ACL 6 -#define TOMOYO_TYPE_RMDIR_ACL 7 -#define TOMOYO_TYPE_MKFIFO_ACL 8 -#define TOMOYO_TYPE_MKSOCK_ACL 9 -#define TOMOYO_TYPE_MKBLOCK_ACL 10 -#define TOMOYO_TYPE_MKCHAR_ACL 11 -#define TOMOYO_TYPE_TRUNCATE_ACL 12 -#define TOMOYO_TYPE_SYMLINK_ACL 13 -#define TOMOYO_TYPE_REWRITE_ACL 14 -#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_TYPE_PIVOT_ROOT_ACL 2 -#define TOMOYO_MAX_DOUBLE_PATH_OPERATION 3 - -#define TOMOYO_DOMAINPOLICY 0 -#define TOMOYO_EXCEPTIONPOLICY 1 -#define TOMOYO_DOMAIN_STATUS 2 -#define TOMOYO_PROCESS_STATUS 3 -#define TOMOYO_MEMINFO 4 -#define TOMOYO_SELFDOMAIN 5 -#define TOMOYO_VERSION 6 -#define TOMOYO_PROFILE 7 -#define TOMOYO_MANAGER 8 +enum tomoyo_path_acl_index { + TOMOYO_TYPE_READ_WRITE_ACL, + TOMOYO_TYPE_EXECUTE_ACL, + TOMOYO_TYPE_READ_ACL, + TOMOYO_TYPE_WRITE_ACL, + TOMOYO_TYPE_CREATE_ACL, + TOMOYO_TYPE_UNLINK_ACL, + TOMOYO_TYPE_MKDIR_ACL, + TOMOYO_TYPE_RMDIR_ACL, + TOMOYO_TYPE_MKFIFO_ACL, + TOMOYO_TYPE_MKSOCK_ACL, + TOMOYO_TYPE_MKBLOCK_ACL, + TOMOYO_TYPE_MKCHAR_ACL, + TOMOYO_TYPE_TRUNCATE_ACL, + TOMOYO_TYPE_SYMLINK_ACL, + TOMOYO_TYPE_REWRITE_ACL, + TOMOYO_TYPE_IOCTL_ACL, + TOMOYO_TYPE_CHMOD_ACL, + TOMOYO_TYPE_CHOWN_ACL, + TOMOYO_TYPE_CHGRP_ACL, + TOMOYO_TYPE_CHROOT_ACL, + TOMOYO_TYPE_MOUNT_ACL, + TOMOYO_TYPE_UMOUNT_ACL, + TOMOYO_MAX_SINGLE_PATH_OPERATION +}; + +enum tomoyo_path2_acl_index { + TOMOYO_TYPE_LINK_ACL, + TOMOYO_TYPE_RENAME_ACL, + TOMOYO_TYPE_PIVOT_ROOT_ACL, + TOMOYO_MAX_DOUBLE_PATH_OPERATION +}; + +enum tomoyo_securityfs_interface_index { + TOMOYO_DOMAINPOLICY, + TOMOYO_EXCEPTIONPOLICY, + TOMOYO_DOMAIN_STATUS, + TOMOYO_PROCESS_STATUS, + TOMOYO_MEMINFO, + TOMOYO_SELFDOMAIN, + TOMOYO_VERSION, + TOMOYO_PROFILE, + TOMOYO_MANAGER +}; /********** Structure definitions. **********/ -- cgit v1.1 From 7ef612331fb219620cc1abfc2446bb027d388aa0 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Tue, 16 Feb 2010 08:03:30 +0900 Subject: TOMOYO: Use shorter names. Use shorter name to reduce newlines needed for 80 columns limit. Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/common.c | 74 +++++------- security/tomoyo/common.h | 90 +++++++-------- security/tomoyo/file.c | 295 ++++++++++++++++++++++------------------------- security/tomoyo/gc.c | 18 +-- security/tomoyo/tomoyo.c | 72 +++++------- 5 files changed, 250 insertions(+), 299 deletions(-) (limited to 'security/tomoyo') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 3a36b56..ffcf024 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -841,25 +841,22 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain) return true; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { switch (ptr->type) { - struct tomoyo_single_path_acl_record *acl; + struct tomoyo_path_acl *acl; u32 perm; u8 i; - case TOMOYO_TYPE_SINGLE_PATH_ACL: - acl = container_of(ptr, - struct tomoyo_single_path_acl_record, - head); + case TOMOYO_TYPE_PATH_ACL: + acl = container_of(ptr, struct tomoyo_path_acl, head); perm = acl->perm | (((u32) acl->perm_high) << 16); - for (i = 0; i < TOMOYO_MAX_SINGLE_PATH_OPERATION; i++) + for (i = 0; i < TOMOYO_MAX_PATH_OPERATION; i++) if (perm & (1 << i)) count++; - if (perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)) + if (perm & (1 << TOMOYO_TYPE_READ_WRITE)) count -= 2; break; - case TOMOYO_TYPE_DOUBLE_PATH_ACL: - perm = container_of(ptr, - struct tomoyo_double_path_acl_record, - head)->perm; - for (i = 0; i < TOMOYO_MAX_DOUBLE_PATH_OPERATION; i++) + case TOMOYO_TYPE_PATH2_ACL: + perm = container_of(ptr, struct tomoyo_path2_acl, head) + ->perm; + for (i = 0; i < TOMOYO_MAX_PATH2_OPERATION; i++) if (perm & (1 << i)) count++; break; @@ -1366,16 +1363,15 @@ static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head) } /** - * tomoyo_print_single_path_acl - Print a single path ACL entry. + * tomoyo_print_path_acl - Print a single path ACL entry. * * @head: Pointer to "struct tomoyo_io_buffer". - * @ptr: Pointer to "struct tomoyo_single_path_acl_record". + * @ptr: Pointer to "struct tomoyo_path_acl". * * Returns true on success, false otherwise. */ -static bool tomoyo_print_single_path_acl(struct tomoyo_io_buffer *head, - struct tomoyo_single_path_acl_record * - ptr) +static bool tomoyo_print_path_acl(struct tomoyo_io_buffer *head, + struct tomoyo_path_acl *ptr) { int pos; u8 bit; @@ -1384,17 +1380,15 @@ static bool tomoyo_print_single_path_acl(struct tomoyo_io_buffer *head, 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; - bit++) { + for (bit = head->read_bit; bit < TOMOYO_MAX_PATH_OPERATION; bit++) { const char *msg; if (!(perm & (1 << bit))) continue; /* Print "read/write" instead of "read" and "write". */ - if ((bit == TOMOYO_TYPE_READ_ACL || - bit == TOMOYO_TYPE_WRITE_ACL) - && (perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))) + if ((bit == TOMOYO_TYPE_READ || bit == TOMOYO_TYPE_WRITE) + && (perm & (1 << TOMOYO_TYPE_READ_WRITE))) continue; - msg = tomoyo_sp2keyword(bit); + msg = tomoyo_path2keyword(bit); pos = head->read_avail; if (!tomoyo_io_printf(head, "allow_%s %s%s\n", msg, atmark, filename)) @@ -1409,16 +1403,15 @@ static bool tomoyo_print_single_path_acl(struct tomoyo_io_buffer *head, } /** - * tomoyo_print_double_path_acl - Print a double path ACL entry. + * tomoyo_print_path2_acl - Print a double path ACL entry. * * @head: Pointer to "struct tomoyo_io_buffer". - * @ptr: Pointer to "struct tomoyo_double_path_acl_record". + * @ptr: Pointer to "struct tomoyo_path2_acl". * * Returns true on success, false otherwise. */ -static bool tomoyo_print_double_path_acl(struct tomoyo_io_buffer *head, - struct tomoyo_double_path_acl_record * - ptr) +static bool tomoyo_print_path2_acl(struct tomoyo_io_buffer *head, + struct tomoyo_path2_acl *ptr) { int pos; const char *atmark1 = ""; @@ -1430,12 +1423,11 @@ static bool tomoyo_print_double_path_acl(struct tomoyo_io_buffer *head, filename1 = ptr->filename1->name; filename2 = ptr->filename2->name; - for (bit = head->read_bit; bit < TOMOYO_MAX_DOUBLE_PATH_OPERATION; - bit++) { + for (bit = head->read_bit; bit < TOMOYO_MAX_PATH2_OPERATION; bit++) { const char *msg; if (!(perm & (1 << bit))) continue; - msg = tomoyo_dp2keyword(bit); + msg = tomoyo_path22keyword(bit); pos = head->read_avail; if (!tomoyo_io_printf(head, "allow_%s %s%s %s%s\n", msg, atmark1, filename1, atmark2, filename2)) @@ -1462,19 +1454,15 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, { const u8 acl_type = ptr->type; - if (acl_type == TOMOYO_TYPE_SINGLE_PATH_ACL) { - struct tomoyo_single_path_acl_record *acl - = container_of(ptr, - struct tomoyo_single_path_acl_record, - head); - return tomoyo_print_single_path_acl(head, acl); + if (acl_type == TOMOYO_TYPE_PATH_ACL) { + struct tomoyo_path_acl *acl + = container_of(ptr, struct tomoyo_path_acl, head); + return tomoyo_print_path_acl(head, acl); } - if (acl_type == TOMOYO_TYPE_DOUBLE_PATH_ACL) { - struct tomoyo_double_path_acl_record *acl - = container_of(ptr, - struct tomoyo_double_path_acl_record, - head); - return tomoyo_print_double_path_acl(head, acl); + if (acl_type == TOMOYO_TYPE_PATH2_ACL) { + struct tomoyo_path2_acl *acl + = container_of(ptr, struct tomoyo_path2_acl, head); + return tomoyo_print_path2_acl(head, acl); } BUG(); /* This must not happen. */ return false; diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 3727296..f4d3050 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -71,8 +71,8 @@ enum tomoyo_mac_index { /* Index numbers for Access Controls. */ enum tomoyo_acl_entry_type_index { - TOMOYO_TYPE_SINGLE_PATH_ACL, - TOMOYO_TYPE_DOUBLE_PATH_ACL, + TOMOYO_TYPE_PATH_ACL, + TOMOYO_TYPE_PATH2_ACL, }; /* Index numbers for File Controls. */ @@ -87,36 +87,36 @@ enum tomoyo_acl_entry_type_index { */ enum tomoyo_path_acl_index { - TOMOYO_TYPE_READ_WRITE_ACL, - TOMOYO_TYPE_EXECUTE_ACL, - TOMOYO_TYPE_READ_ACL, - TOMOYO_TYPE_WRITE_ACL, - TOMOYO_TYPE_CREATE_ACL, - TOMOYO_TYPE_UNLINK_ACL, - TOMOYO_TYPE_MKDIR_ACL, - TOMOYO_TYPE_RMDIR_ACL, - TOMOYO_TYPE_MKFIFO_ACL, - TOMOYO_TYPE_MKSOCK_ACL, - TOMOYO_TYPE_MKBLOCK_ACL, - TOMOYO_TYPE_MKCHAR_ACL, - TOMOYO_TYPE_TRUNCATE_ACL, - TOMOYO_TYPE_SYMLINK_ACL, - TOMOYO_TYPE_REWRITE_ACL, - TOMOYO_TYPE_IOCTL_ACL, - TOMOYO_TYPE_CHMOD_ACL, - TOMOYO_TYPE_CHOWN_ACL, - TOMOYO_TYPE_CHGRP_ACL, - TOMOYO_TYPE_CHROOT_ACL, - TOMOYO_TYPE_MOUNT_ACL, - TOMOYO_TYPE_UMOUNT_ACL, - TOMOYO_MAX_SINGLE_PATH_OPERATION + TOMOYO_TYPE_READ_WRITE, + TOMOYO_TYPE_EXECUTE, + TOMOYO_TYPE_READ, + TOMOYO_TYPE_WRITE, + TOMOYO_TYPE_CREATE, + TOMOYO_TYPE_UNLINK, + TOMOYO_TYPE_MKDIR, + TOMOYO_TYPE_RMDIR, + TOMOYO_TYPE_MKFIFO, + TOMOYO_TYPE_MKSOCK, + TOMOYO_TYPE_MKBLOCK, + TOMOYO_TYPE_MKCHAR, + TOMOYO_TYPE_TRUNCATE, + TOMOYO_TYPE_SYMLINK, + TOMOYO_TYPE_REWRITE, + TOMOYO_TYPE_IOCTL, + TOMOYO_TYPE_CHMOD, + TOMOYO_TYPE_CHOWN, + TOMOYO_TYPE_CHGRP, + TOMOYO_TYPE_CHROOT, + TOMOYO_TYPE_MOUNT, + TOMOYO_TYPE_UMOUNT, + TOMOYO_MAX_PATH_OPERATION }; enum tomoyo_path2_acl_index { - TOMOYO_TYPE_LINK_ACL, - TOMOYO_TYPE_RENAME_ACL, - TOMOYO_TYPE_PIVOT_ROOT_ACL, - TOMOYO_MAX_DOUBLE_PATH_OPERATION + TOMOYO_TYPE_LINK, + TOMOYO_TYPE_RENAME, + TOMOYO_TYPE_PIVOT_ROOT, + TOMOYO_MAX_PATH2_OPERATION }; enum tomoyo_securityfs_interface_index { @@ -210,12 +210,11 @@ struct tomoyo_path_info_with_data { * (1) "list" which is linked to the ->acl_info_list of * "struct tomoyo_domain_info" * (2) "type" which tells type of the entry (either - * "struct tomoyo_single_path_acl_record" or - * "struct tomoyo_double_path_acl_record"). + * "struct tomoyo_path_acl" or "struct tomoyo_path2_acl"). * * Packing "struct tomoyo_acl_info" allows - * "struct tomoyo_single_path_acl_record" to embed "u8" + "u16" and - * "struct tomoyo_double_path_acl_record" to embed "u8" + * "struct tomoyo_path_acl" to embed "u8" + "u16" and + * "struct tomoyo_path2_acl" to embed "u8" * without enlarging their structure size. */ struct tomoyo_acl_info { @@ -269,7 +268,7 @@ struct tomoyo_domain_info { }; /* - * tomoyo_single_path_acl_record is a structure which is used for holding an + * tomoyo_path_acl is a structure which is used for holding an * entry with one pathname operation (e.g. open(), mkdir()). * It has following fields. * @@ -284,8 +283,8 @@ struct tomoyo_domain_info { * "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 */ +struct tomoyo_path_acl { + struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_ACL */ u8 perm_high; u16 perm; /* Pointer to single pathname. */ @@ -293,7 +292,7 @@ struct tomoyo_single_path_acl_record { }; /* - * tomoyo_double_path_acl_record is a structure which is used for holding an + * tomoyo_path2_acl is a structure which is used for holding an * entry with two pathnames operation (i.e. link(), rename() and pivot_root()). * It has following fields. * @@ -305,8 +304,8 @@ struct tomoyo_single_path_acl_record { * 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 */ +struct tomoyo_path2_acl { + struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH2_ACL */ u8 perm; /* Pointer to single pathname. */ const struct tomoyo_path_info *filename1; @@ -550,13 +549,13 @@ bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head); /* Write domain policy violation warning message to console? */ bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain); /* Convert double path operation to operation name. */ -const char *tomoyo_dp2keyword(const u8 operation); +const char *tomoyo_path22keyword(const u8 operation); /* Get the last component of the given domainname. */ const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain); /* Get warning message. */ const char *tomoyo_get_msg(const bool is_enforce); /* Convert single path operation to operation name. */ -const char *tomoyo_sp2keyword(const u8 operation); +const char *tomoyo_path2keyword(const u8 operation); /* Create "alias" entry in exception policy. */ int tomoyo_write_alias_policy(char *data, const bool is_delete); /* @@ -638,11 +637,10 @@ int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, const struct tomoyo_path_info *filename); int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, struct path *path, const int flag); -int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain, - const u8 operation, struct path *path); -int tomoyo_check_2path_perm(struct tomoyo_domain_info *domain, - const u8 operation, struct path *path1, - struct path *path2); +int tomoyo_path_perm(struct tomoyo_domain_info *domain, const u8 operation, + struct path *path); +int tomoyo_path2_perm(struct tomoyo_domain_info *domain, const u8 operation, + struct path *path1, struct path *path2); int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, struct file *filp); int tomoyo_find_next_domain(struct linux_binprm *bprm); diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 10ee7ce..09feaf2 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -12,62 +12,62 @@ #include "common.h" /* 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", - [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", +static const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = { + [TOMOYO_TYPE_READ_WRITE] = "read/write", + [TOMOYO_TYPE_EXECUTE] = "execute", + [TOMOYO_TYPE_READ] = "read", + [TOMOYO_TYPE_WRITE] = "write", + [TOMOYO_TYPE_CREATE] = "create", + [TOMOYO_TYPE_UNLINK] = "unlink", + [TOMOYO_TYPE_MKDIR] = "mkdir", + [TOMOYO_TYPE_RMDIR] = "rmdir", + [TOMOYO_TYPE_MKFIFO] = "mkfifo", + [TOMOYO_TYPE_MKSOCK] = "mksock", + [TOMOYO_TYPE_MKBLOCK] = "mkblock", + [TOMOYO_TYPE_MKCHAR] = "mkchar", + [TOMOYO_TYPE_TRUNCATE] = "truncate", + [TOMOYO_TYPE_SYMLINK] = "symlink", + [TOMOYO_TYPE_REWRITE] = "rewrite", + [TOMOYO_TYPE_IOCTL] = "ioctl", + [TOMOYO_TYPE_CHMOD] = "chmod", + [TOMOYO_TYPE_CHOWN] = "chown", + [TOMOYO_TYPE_CHGRP] = "chgrp", + [TOMOYO_TYPE_CHROOT] = "chroot", + [TOMOYO_TYPE_MOUNT] = "mount", + [TOMOYO_TYPE_UMOUNT] = "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", +static const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION] = { + [TOMOYO_TYPE_LINK] = "link", + [TOMOYO_TYPE_RENAME] = "rename", + [TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root", }; /** - * tomoyo_sp2keyword - Get the name of single path operation. + * tomoyo_path2keyword - 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) +const char *tomoyo_path2keyword(const u8 operation) { - return (operation < TOMOYO_MAX_SINGLE_PATH_OPERATION) - ? tomoyo_sp_keyword[operation] : NULL; + return (operation < TOMOYO_MAX_PATH_OPERATION) + ? tomoyo_path_keyword[operation] : NULL; } /** - * tomoyo_dp2keyword - Get the name of double path operation. + * tomoyo_path22keyword - 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) +const char *tomoyo_path22keyword(const u8 operation) { - return (operation < TOMOYO_MAX_DOUBLE_PATH_OPERATION) - ? tomoyo_dp_keyword[operation] : NULL; + return (operation < TOMOYO_MAX_PATH2_OPERATION) + ? tomoyo_path2_keyword[operation] : NULL; } /** @@ -115,13 +115,13 @@ static struct tomoyo_path_info *tomoyo_get_path(struct path *path) return NULL; } -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); +static int tomoyo_update_path2_acl(const u8 type, const char *filename1, + const char *filename2, + struct tomoyo_domain_info *const domain, + const bool is_delete); +static int tomoyo_update_path_acl(const u8 type, const char *filename, + struct tomoyo_domain_info *const domain, + const bool is_delete); /* * tomoyo_globally_readable_list is used for holding list of pathnames which @@ -597,19 +597,19 @@ static int tomoyo_update_file_acl(const char *filename, u8 perm, */ return 0; if (perm & 4) - tomoyo_update_single_path_acl(TOMOYO_TYPE_READ_ACL, filename, - domain, is_delete); + tomoyo_update_path_acl(TOMOYO_TYPE_READ, filename, domain, + is_delete); if (perm & 2) - tomoyo_update_single_path_acl(TOMOYO_TYPE_WRITE_ACL, filename, - domain, is_delete); + tomoyo_update_path_acl(TOMOYO_TYPE_WRITE, filename, domain, + is_delete); if (perm & 1) - tomoyo_update_single_path_acl(TOMOYO_TYPE_EXECUTE_ACL, - filename, domain, is_delete); + tomoyo_update_path_acl(TOMOYO_TYPE_EXECUTE, filename, domain, + is_delete); return 0; } /** - * tomoyo_check_single_path_acl2 - Check permission for single path operation. + * tomoyo_path_acl2 - Check permission for single path operation. * * @domain: Pointer to "struct tomoyo_domain_info". * @filename: Filename to check. @@ -620,22 +620,18 @@ static int tomoyo_update_file_acl(const char *filename, u8 perm, * * Caller holds tomoyo_read_lock(). */ -static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info * - domain, - const struct tomoyo_path_info * - filename, - const u32 perm, - const bool may_use_pattern) +static int tomoyo_path_acl2(const struct tomoyo_domain_info *domain, + const struct tomoyo_path_info *filename, + const u32 perm, const bool may_use_pattern) { struct tomoyo_acl_info *ptr; int error = -EPERM; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - struct tomoyo_single_path_acl_record *acl; - if (ptr->type != TOMOYO_TYPE_SINGLE_PATH_ACL) + struct tomoyo_path_acl *acl; + if (ptr->type != TOMOYO_TYPE_PATH_ACL) continue; - acl = container_of(ptr, struct tomoyo_single_path_acl_record, - head); + acl = container_of(ptr, struct tomoyo_path_acl, head); if (perm <= 0xFFFF) { if (!(acl->perm & perm)) continue; @@ -676,17 +672,16 @@ static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain, if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) return 0; if (operation == 6) - perm = 1 << TOMOYO_TYPE_READ_WRITE_ACL; + perm = 1 << TOMOYO_TYPE_READ_WRITE; else if (operation == 4) - perm = 1 << TOMOYO_TYPE_READ_ACL; + perm = 1 << TOMOYO_TYPE_READ; else if (operation == 2) - perm = 1 << TOMOYO_TYPE_WRITE_ACL; + perm = 1 << TOMOYO_TYPE_WRITE; else if (operation == 1) - perm = 1 << TOMOYO_TYPE_EXECUTE_ACL; + perm = 1 << TOMOYO_TYPE_EXECUTE; else BUG(); - return tomoyo_check_single_path_acl2(domain, filename, perm, - operation != 1); + return tomoyo_path_acl2(domain, filename, perm, operation != 1); } /** @@ -718,13 +713,13 @@ static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain, && tomoyo_is_globally_readable_file(filename)) error = 0; if (perm == 6) - msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_WRITE_ACL); + msg = tomoyo_path2keyword(TOMOYO_TYPE_READ_WRITE); else if (perm == 4) - msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_ACL); + msg = tomoyo_path2keyword(TOMOYO_TYPE_READ); else if (perm == 2) - msg = tomoyo_sp2keyword(TOMOYO_TYPE_WRITE_ACL); + msg = tomoyo_path2keyword(TOMOYO_TYPE_WRITE); else if (perm == 1) - msg = tomoyo_sp2keyword(TOMOYO_TYPE_EXECUTE_ACL); + msg = tomoyo_path2keyword(TOMOYO_TYPE_EXECUTE); else BUG(); if (!error) @@ -773,28 +768,28 @@ int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, 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])) + for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) { + if (strcmp(data, tomoyo_path_keyword[type])) continue; - return tomoyo_update_single_path_acl(type, filename, - domain, is_delete); + return tomoyo_update_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])) + for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) { + if (strcmp(data, tomoyo_path2_keyword[type])) continue; - return tomoyo_update_double_path_acl(type, filename, filename2, - domain, is_delete); + return tomoyo_update_path2_acl(type, filename, filename2, + domain, is_delete); } out: return -EINVAL; } /** - * tomoyo_update_single_path_acl - Update "struct tomoyo_single_path_acl_record" list. + * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list. * * @type: Type of operation. * @filename: Filename. @@ -805,15 +800,15 @@ int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, * * Caller holds tomoyo_read_lock(). */ -static int tomoyo_update_single_path_acl(const u8 type, const char *filename, - struct tomoyo_domain_info * - const domain, const bool is_delete) +static int tomoyo_update_path_acl(const u8 type, const char *filename, + struct tomoyo_domain_info *const domain, + const bool is_delete) { static const u32 rw_mask = - (1 << TOMOYO_TYPE_READ_ACL) | (1 << TOMOYO_TYPE_WRITE_ACL); + (1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE); const struct tomoyo_path_info *saved_filename; struct tomoyo_acl_info *ptr; - struct tomoyo_single_path_acl_record *entry = NULL; + struct tomoyo_path_acl *entry = NULL; int error = is_delete ? -ENOENT : -ENOMEM; const u32 perm = 1 << type; @@ -828,10 +823,9 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, entry = kmalloc(sizeof(*entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - struct tomoyo_single_path_acl_record *acl = - container_of(ptr, struct tomoyo_single_path_acl_record, - head); - if (ptr->type != TOMOYO_TYPE_SINGLE_PATH_ACL) + struct tomoyo_path_acl *acl = + container_of(ptr, struct tomoyo_path_acl, head); + if (ptr->type != TOMOYO_TYPE_PATH_ACL) continue; if (acl->filename != saved_filename) continue; @@ -841,9 +835,8 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, 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 &= ~(1 << TOMOYO_TYPE_READ_WRITE); + else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE))) acl->perm &= ~rw_mask; } else { if (perm <= 0xFFFF) @@ -851,20 +844,20 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, 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 |= 1 << TOMOYO_TYPE_READ_WRITE; + else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE)) acl->perm |= rw_mask; } error = 0; break; } if (!is_delete && error && tomoyo_memory_ok(entry)) { - entry->head.type = TOMOYO_TYPE_SINGLE_PATH_ACL; + entry->head.type = TOMOYO_TYPE_PATH_ACL; if (perm <= 0xFFFF) entry->perm = perm; else entry->perm_high = (perm >> 16); - if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL)) + if (perm == (1 << TOMOYO_TYPE_READ_WRITE)) entry->perm |= rw_mask; entry->filename = saved_filename; saved_filename = NULL; @@ -879,7 +872,7 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, } /** - * tomoyo_update_double_path_acl - Update "struct tomoyo_double_path_acl_record" list. + * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list. * * @type: Type of operation. * @filename1: First filename. @@ -891,15 +884,15 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, * * Caller holds tomoyo_read_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_path2_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 *entry = NULL; + struct tomoyo_path2_acl *entry = NULL; int error = is_delete ? -ENOENT : -ENOMEM; const u8 perm = 1 << type; @@ -916,10 +909,9 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, entry = kmalloc(sizeof(*entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - struct tomoyo_double_path_acl_record *acl = - container_of(ptr, struct tomoyo_double_path_acl_record, - head); - if (ptr->type != TOMOYO_TYPE_DOUBLE_PATH_ACL) + struct tomoyo_path2_acl *acl = + container_of(ptr, struct tomoyo_path2_acl, head); + if (ptr->type != TOMOYO_TYPE_PATH2_ACL) continue; if (acl->filename1 != saved_filename1 || acl->filename2 != saved_filename2) @@ -932,7 +924,7 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, break; } if (!is_delete && error && tomoyo_memory_ok(entry)) { - entry->head.type = TOMOYO_TYPE_DOUBLE_PATH_ACL; + entry->head.type = TOMOYO_TYPE_PATH2_ACL; entry->perm = perm; entry->filename1 = saved_filename1; saved_filename1 = NULL; @@ -951,7 +943,7 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, } /** - * tomoyo_check_single_path_acl - Check permission for single path operation. + * tomoyo_path_acl - Check permission for single path operation. * * @domain: Pointer to "struct tomoyo_domain_info". * @type: Type of operation. @@ -961,17 +953,16 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, * * Caller holds tomoyo_read_lock(). */ -static int tomoyo_check_single_path_acl(struct tomoyo_domain_info *domain, - const u8 type, - const struct tomoyo_path_info *filename) +static int tomoyo_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); + return tomoyo_path_acl2(domain, filename, 1 << type, 1); } /** - * tomoyo_check_double_path_acl - Check permission for double path operation. + * tomoyo_path2_acl - Check permission for double path operation. * * @domain: Pointer to "struct tomoyo_domain_info". * @type: Type of operation. @@ -982,12 +973,10 @@ static int tomoyo_check_single_path_acl(struct tomoyo_domain_info *domain, * * Caller holds tomoyo_read_lock(). */ -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) +static int tomoyo_path2_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; @@ -996,11 +985,10 @@ static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain, if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) return 0; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - struct tomoyo_double_path_acl_record *acl; - if (ptr->type != TOMOYO_TYPE_DOUBLE_PATH_ACL) + struct tomoyo_path2_acl *acl; + if (ptr->type != TOMOYO_TYPE_PATH2_ACL) continue; - acl = container_of(ptr, struct tomoyo_double_path_acl_record, - head); + acl = container_of(ptr, struct tomoyo_path2_acl, head); if (!(acl->perm & perm)) continue; if (!tomoyo_path_matches_pattern(filename1, acl->filename1)) @@ -1014,7 +1002,7 @@ static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain, } /** - * tomoyo_check_single_path_permission2 - Check permission for single path operation. + * tomoyo_path_permission2 - Check permission for single path operation. * * @domain: Pointer to "struct tomoyo_domain_info". * @operation: Type of operation. @@ -1025,10 +1013,10 @@ static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain, * * Caller holds tomoyo_read_lock(). */ -static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info * - const domain, u8 operation, - const struct tomoyo_path_info * - filename, const u8 mode) +static int tomoyo_path_permission2(struct tomoyo_domain_info *const domain, + u8 operation, + const struct tomoyo_path_info *filename, + const u8 mode) { const char *msg; int error; @@ -1037,8 +1025,8 @@ static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info * if (!mode) return 0; next: - error = tomoyo_check_single_path_acl(domain, operation, filename); - msg = tomoyo_sp2keyword(operation); + error = tomoyo_path_acl(domain, operation, filename); + msg = tomoyo_path2keyword(operation); if (!error) goto ok; if (tomoyo_verbose_mode(domain)) @@ -1047,7 +1035,7 @@ static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info * 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); + tomoyo_update_path_acl(operation, name, domain, false); } if (!is_enforce) error = 0; @@ -1057,9 +1045,9 @@ static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info * * we need to check "allow_rewrite" permission if the filename is * specified by "deny_rewrite" keyword. */ - if (!error && operation == TOMOYO_TYPE_TRUNCATE_ACL && + if (!error && operation == TOMOYO_TYPE_TRUNCATE && tomoyo_is_no_rewrite_file(filename)) { - operation = TOMOYO_TYPE_REWRITE_ACL; + operation = TOMOYO_TYPE_REWRITE; goto next; } return error; @@ -1127,17 +1115,15 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, 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); + error = tomoyo_path_permission2(domain, TOMOYO_TYPE_REWRITE, + 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); + error = tomoyo_path_permission2(domain, TOMOYO_TYPE_TRUNCATE, + buf, mode); out: kfree(buf); tomoyo_read_unlock(idx); @@ -1147,7 +1133,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", "symlink", "ioctl", "chmod", "chown", "chgrp", "chroot", "mount" and "unmount". + * tomoyo_path_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. @@ -1155,8 +1141,8 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, * * Returns 0 on success, negative value otherwise. */ -int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain, - const u8 operation, struct path *path) +int tomoyo_path_perm(struct tomoyo_domain_info *domain, + const u8 operation, struct path *path) { int error = -ENOMEM; struct tomoyo_path_info *buf; @@ -1171,9 +1157,9 @@ int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain, if (!buf) goto out; switch (operation) { - case TOMOYO_TYPE_MKDIR_ACL: - case TOMOYO_TYPE_RMDIR_ACL: - case TOMOYO_TYPE_CHROOT_ACL: + case TOMOYO_TYPE_MKDIR: + case TOMOYO_TYPE_RMDIR: + case TOMOYO_TYPE_CHROOT: if (!buf->is_dir) { /* * tomoyo_get_path() reserves space for appending "/." @@ -1182,8 +1168,7 @@ int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain, tomoyo_fill_path_info(buf); } } - error = tomoyo_check_single_path_permission2(domain, operation, buf, - mode); + error = tomoyo_path_permission2(domain, operation, buf, mode); out: kfree(buf); tomoyo_read_unlock(idx); @@ -1220,9 +1205,7 @@ int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, error = 0; goto out; } - error = tomoyo_check_single_path_permission2(domain, - TOMOYO_TYPE_REWRITE_ACL, - buf, mode); + error = tomoyo_path_permission2(domain, TOMOYO_TYPE_REWRITE, buf, mode); out: kfree(buf); tomoyo_read_unlock(idx); @@ -1232,7 +1215,7 @@ int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, } /** - * tomoyo_check_2path_perm - Check permission for "rename", "link" and "pivot_root". + * tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root". * * @domain: Pointer to "struct tomoyo_domain_info". * @operation: Type of operation. @@ -1241,9 +1224,9 @@ int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, * * 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 tomoyo_path2_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; @@ -1275,8 +1258,8 @@ int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain, } } } - error = tomoyo_check_double_path_acl(domain, operation, buf1, buf2); - msg = tomoyo_dp2keyword(operation); + error = tomoyo_path2_acl(domain, operation, buf1, buf2); + msg = tomoyo_path22keyword(operation); if (!error) goto out; if (tomoyo_verbose_mode(domain)) @@ -1287,8 +1270,8 @@ int tomoyo_check_2path_perm(struct tomoyo_domain_info * const 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); + tomoyo_update_path2_acl(operation, name1, name2, domain, + false); } out: kfree(buf1); diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c index ee15da3..9645525 100644 --- a/security/tomoyo/gc.c +++ b/security/tomoyo/gc.c @@ -86,16 +86,16 @@ static void tomoyo_del_manager(struct tomoyo_policy_manager_entry *ptr) static void tomoyo_del_acl(struct tomoyo_acl_info *acl) { switch (acl->type) { - case TOMOYO_TYPE_SINGLE_PATH_ACL: + case TOMOYO_TYPE_PATH_ACL: { - struct tomoyo_single_path_acl_record *entry + struct tomoyo_path_acl *entry = container_of(acl, typeof(*entry), head); tomoyo_put_name(entry->filename); } break; - case TOMOYO_TYPE_DOUBLE_PATH_ACL: + case TOMOYO_TYPE_PATH2_ACL: { - struct tomoyo_double_path_acl_record *entry + struct tomoyo_path2_acl *entry = container_of(acl, typeof(*entry), head); tomoyo_put_name(entry->filename1); tomoyo_put_name(entry->filename2); @@ -238,18 +238,18 @@ static void tomoyo_collect_entry(void) list_for_each_entry_rcu(acl, &domain->acl_info_list, list) { switch (acl->type) { - case TOMOYO_TYPE_SINGLE_PATH_ACL: + case TOMOYO_TYPE_PATH_ACL: if (container_of(acl, - struct tomoyo_single_path_acl_record, + struct tomoyo_path_acl, head)->perm || container_of(acl, - struct tomoyo_single_path_acl_record, + struct tomoyo_path_acl, head)->perm_high) continue; break; - case TOMOYO_TYPE_DOUBLE_PATH_ACL: + case TOMOYO_TYPE_PATH2_ACL: if (container_of(acl, - struct tomoyo_double_path_acl_record, + struct tomoyo_path2_acl, head)->perm) continue; break; diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 87e82bf..e3945d0 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -100,67 +100,56 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm) static int tomoyo_path_truncate(struct path *path, loff_t length, unsigned int time_attrs) { - return tomoyo_check_1path_perm(tomoyo_domain(), - TOMOYO_TYPE_TRUNCATE_ACL, - path); + return tomoyo_path_perm(tomoyo_domain(), TOMOYO_TYPE_TRUNCATE, path); } static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry) { struct path path = { parent->mnt, dentry }; - return tomoyo_check_1path_perm(tomoyo_domain(), - TOMOYO_TYPE_UNLINK_ACL, - &path); + return tomoyo_path_perm(tomoyo_domain(), TOMOYO_TYPE_UNLINK, &path); } static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry, int mode) { struct path path = { parent->mnt, dentry }; - return tomoyo_check_1path_perm(tomoyo_domain(), - TOMOYO_TYPE_MKDIR_ACL, - &path); + return tomoyo_path_perm(tomoyo_domain(), TOMOYO_TYPE_MKDIR, &path); } static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry) { struct path path = { parent->mnt, dentry }; - return tomoyo_check_1path_perm(tomoyo_domain(), - TOMOYO_TYPE_RMDIR_ACL, - &path); + return tomoyo_path_perm(tomoyo_domain(), TOMOYO_TYPE_RMDIR, &path); } static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry, const char *old_name) { struct path path = { parent->mnt, dentry }; - return tomoyo_check_1path_perm(tomoyo_domain(), - TOMOYO_TYPE_SYMLINK_ACL, - &path); + return tomoyo_path_perm(tomoyo_domain(), TOMOYO_TYPE_SYMLINK, &path); } static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry, int mode, unsigned int dev) { struct path path = { parent->mnt, dentry }; - int type = TOMOYO_TYPE_CREATE_ACL; + int type = TOMOYO_TYPE_CREATE; switch (mode & S_IFMT) { case S_IFCHR: - type = TOMOYO_TYPE_MKCHAR_ACL; + type = TOMOYO_TYPE_MKCHAR; break; case S_IFBLK: - type = TOMOYO_TYPE_MKBLOCK_ACL; + type = TOMOYO_TYPE_MKBLOCK; break; case S_IFIFO: - type = TOMOYO_TYPE_MKFIFO_ACL; + type = TOMOYO_TYPE_MKFIFO; break; case S_IFSOCK: - type = TOMOYO_TYPE_MKSOCK_ACL; + type = TOMOYO_TYPE_MKSOCK; break; } - return tomoyo_check_1path_perm(tomoyo_domain(), - type, &path); + return tomoyo_path_perm(tomoyo_domain(), type, &path); } static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir, @@ -168,9 +157,8 @@ static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir, { struct path path1 = { new_dir->mnt, old_dentry }; struct path path2 = { new_dir->mnt, new_dentry }; - return tomoyo_check_2path_perm(tomoyo_domain(), - TOMOYO_TYPE_LINK_ACL, - &path1, &path2); + return tomoyo_path2_perm(tomoyo_domain(), TOMOYO_TYPE_LINK, &path1, + &path2); } static int tomoyo_path_rename(struct path *old_parent, @@ -180,9 +168,8 @@ static int tomoyo_path_rename(struct path *old_parent, { struct path path1 = { old_parent->mnt, old_dentry }; struct path path2 = { new_parent->mnt, new_dentry }; - return tomoyo_check_2path_perm(tomoyo_domain(), - TOMOYO_TYPE_RENAME_ACL, - &path1, &path2); + return tomoyo_path2_perm(tomoyo_domain(), TOMOYO_TYPE_RENAME, &path1, + &path2); } static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, @@ -209,55 +196,50 @@ static int tomoyo_dentry_open(struct file *f, const struct cred *cred) 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); + return tomoyo_path_perm(tomoyo_domain(), TOMOYO_TYPE_IOCTL, + &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); + return tomoyo_path_perm(tomoyo_domain(), TOMOYO_TYPE_CHMOD, &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); + error = tomoyo_path_perm(tomoyo_domain(), TOMOYO_TYPE_CHOWN, + path); if (!error && gid != (gid_t) -1) - error = tomoyo_check_1path_perm(tomoyo_domain(), - TOMOYO_TYPE_CHGRP_ACL, path); + error = tomoyo_path_perm(tomoyo_domain(), TOMOYO_TYPE_CHGRP, + path); return error; } static int tomoyo_path_chroot(struct path *path) { - return tomoyo_check_1path_perm(tomoyo_domain(), TOMOYO_TYPE_CHROOT_ACL, - path); + return tomoyo_path_perm(tomoyo_domain(), TOMOYO_TYPE_CHROOT, 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); + return tomoyo_path_perm(tomoyo_domain(), TOMOYO_TYPE_MOUNT, 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); + return tomoyo_path_perm(tomoyo_domain(), TOMOYO_TYPE_UMOUNT, &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); + return tomoyo_path2_perm(tomoyo_domain(), TOMOYO_TYPE_PIVOT_ROOT, + new_path, old_path); } /* -- cgit v1.1 From 97d6931ead3e89a764cdaa3ad0924037367f0d34 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Tue, 16 Feb 2010 09:46:15 +0900 Subject: TOMOYO: Remove unneeded parameter. tomoyo_path_perm() tomoyo_path2_perm() and tomoyo_check_rewrite_permission() always receive tomoyo_domain(). We can move it from caller to callee. Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/common.h | 10 ++++------ security/tomoyo/file.c | 15 ++++++--------- security/tomoyo/tomoyo.c | 40 +++++++++++++++++----------------------- 3 files changed, 27 insertions(+), 38 deletions(-) (limited to 'security/tomoyo') diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index f4d3050..17ed365 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -637,12 +637,10 @@ int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, const struct tomoyo_path_info *filename); int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, struct path *path, const int flag); -int tomoyo_path_perm(struct tomoyo_domain_info *domain, const u8 operation, - struct path *path); -int tomoyo_path2_perm(struct tomoyo_domain_info *domain, const u8 operation, - struct path *path1, struct path *path2); -int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, - struct file *filp); +int tomoyo_path_perm(const u8 operation, struct path *path); +int tomoyo_path2_perm(const u8 operation, struct path *path1, + struct path *path2); +int tomoyo_check_rewrite_permission(struct file *filp); int tomoyo_find_next_domain(struct linux_binprm *bprm); /* Run garbage collector. */ diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 09feaf2..db342ef 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -1135,17 +1135,16 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, /** * tomoyo_path_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. * @path: Pointer to "struct path". * * Returns 0 on success, negative value otherwise. */ -int tomoyo_path_perm(struct tomoyo_domain_info *domain, - const u8 operation, struct path *path) +int tomoyo_path_perm(const u8 operation, struct path *path) { int error = -ENOMEM; struct tomoyo_path_info *buf; + struct tomoyo_domain_info *domain = tomoyo_domain(); const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); const bool is_enforce = (mode == 3); int idx; @@ -1180,15 +1179,14 @@ int tomoyo_path_perm(struct tomoyo_domain_info *domain, /** * 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 tomoyo_check_rewrite_permission(struct file *filp) { int error = -ENOMEM; + struct tomoyo_domain_info *domain = tomoyo_domain(); const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); const bool is_enforce = (mode == 3); struct tomoyo_path_info *buf; @@ -1217,19 +1215,18 @@ int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, /** * tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root". * - * @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_path2_perm(struct tomoyo_domain_info * const domain, - const u8 operation, struct path *path1, +int tomoyo_path2_perm(const u8 operation, struct path *path1, struct path *path2) { int error = -ENOMEM; struct tomoyo_path_info *buf1, *buf2; + struct tomoyo_domain_info *domain = tomoyo_domain(); const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); const bool is_enforce = (mode == 3); const char *msg; diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index e3945d0..c94e35c 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -100,33 +100,33 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm) static int tomoyo_path_truncate(struct path *path, loff_t length, unsigned int time_attrs) { - return tomoyo_path_perm(tomoyo_domain(), TOMOYO_TYPE_TRUNCATE, path); + return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path); } static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry) { struct path path = { parent->mnt, dentry }; - return tomoyo_path_perm(tomoyo_domain(), TOMOYO_TYPE_UNLINK, &path); + return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path); } static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry, int mode) { struct path path = { parent->mnt, dentry }; - return tomoyo_path_perm(tomoyo_domain(), TOMOYO_TYPE_MKDIR, &path); + return tomoyo_path_perm(TOMOYO_TYPE_MKDIR, &path); } static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry) { struct path path = { parent->mnt, dentry }; - return tomoyo_path_perm(tomoyo_domain(), TOMOYO_TYPE_RMDIR, &path); + return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path); } static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry, const char *old_name) { struct path path = { parent->mnt, dentry }; - return tomoyo_path_perm(tomoyo_domain(), TOMOYO_TYPE_SYMLINK, &path); + return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path); } static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry, @@ -149,7 +149,7 @@ static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry, type = TOMOYO_TYPE_MKSOCK; break; } - return tomoyo_path_perm(tomoyo_domain(), type, &path); + return tomoyo_path_perm(type, &path); } static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir, @@ -157,8 +157,7 @@ static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir, { struct path path1 = { new_dir->mnt, old_dentry }; struct path path2 = { new_dir->mnt, new_dentry }; - return tomoyo_path2_perm(tomoyo_domain(), TOMOYO_TYPE_LINK, &path1, - &path2); + return tomoyo_path2_perm(TOMOYO_TYPE_LINK, &path1, &path2); } static int tomoyo_path_rename(struct path *old_parent, @@ -168,15 +167,14 @@ static int tomoyo_path_rename(struct path *old_parent, { struct path path1 = { old_parent->mnt, old_dentry }; struct path path2 = { new_parent->mnt, new_dentry }; - return tomoyo_path2_perm(tomoyo_domain(), TOMOYO_TYPE_RENAME, &path1, - &path2); + return tomoyo_path2_perm(TOMOYO_TYPE_RENAME, &path1, &path2); } static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg) { if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND)) - return tomoyo_check_rewrite_permission(tomoyo_domain(), file); + return tomoyo_check_rewrite_permission(file); return 0; } @@ -196,50 +194,46 @@ static int tomoyo_dentry_open(struct file *f, const struct cred *cred) static int tomoyo_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - return tomoyo_path_perm(tomoyo_domain(), TOMOYO_TYPE_IOCTL, - &file->f_path); + return tomoyo_path_perm(TOMOYO_TYPE_IOCTL, &file->f_path); } static int tomoyo_path_chmod(struct dentry *dentry, struct vfsmount *mnt, mode_t mode) { struct path path = { mnt, dentry }; - return tomoyo_path_perm(tomoyo_domain(), TOMOYO_TYPE_CHMOD, &path); + return tomoyo_path_perm(TOMOYO_TYPE_CHMOD, &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_path_perm(tomoyo_domain(), TOMOYO_TYPE_CHOWN, - path); + error = tomoyo_path_perm(TOMOYO_TYPE_CHOWN, path); if (!error && gid != (gid_t) -1) - error = tomoyo_path_perm(tomoyo_domain(), TOMOYO_TYPE_CHGRP, - path); + error = tomoyo_path_perm(TOMOYO_TYPE_CHGRP, path); return error; } static int tomoyo_path_chroot(struct path *path) { - return tomoyo_path_perm(tomoyo_domain(), TOMOYO_TYPE_CHROOT, path); + return tomoyo_path_perm(TOMOYO_TYPE_CHROOT, path); } static int tomoyo_sb_mount(char *dev_name, struct path *path, char *type, unsigned long flags, void *data) { - return tomoyo_path_perm(tomoyo_domain(), TOMOYO_TYPE_MOUNT, path); + return tomoyo_path_perm(TOMOYO_TYPE_MOUNT, path); } static int tomoyo_sb_umount(struct vfsmount *mnt, int flags) { struct path path = { mnt, mnt->mnt_root }; - return tomoyo_path_perm(tomoyo_domain(), TOMOYO_TYPE_UMOUNT, &path); + return tomoyo_path_perm(TOMOYO_TYPE_UMOUNT, &path); } static int tomoyo_sb_pivotroot(struct path *old_path, struct path *new_path) { - return tomoyo_path2_perm(tomoyo_domain(), TOMOYO_TYPE_PIVOT_ROOT, - new_path, old_path); + return tomoyo_path2_perm(TOMOYO_TYPE_PIVOT_ROOT, new_path, old_path); } /* -- cgit v1.1 From 170800088666963de1111d62fb503889c8c82eda Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Tue, 16 Feb 2010 21:14:48 +0900 Subject: TOMOYO: Remove __func__ from tomoyo_is_correct_path/domain __func__ is used for only debug printk(). We can remove it. Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/common.c | 18 ++++-------------- security/tomoyo/common.h | 6 ++---- security/tomoyo/domain.c | 18 +++++++++--------- security/tomoyo/file.c | 10 +++++----- 4 files changed, 20 insertions(+), 32 deletions(-) (limited to 'security/tomoyo') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index ffcf024..30dd1c6 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -179,14 +179,12 @@ static void tomoyo_normalize_line(unsigned char *buffer) * 1 = must / -1 = must not / 0 = don't care * @end_type: Should the pathname end with '/'? * 1 = must / -1 = must not / 0 = don't care - * @function: The name of function calling me. * * Check whether the given filename follows the naming rules. * Returns true if @filename follows the naming rules, false otherwise. */ bool tomoyo_is_correct_path(const char *filename, const s8 start_type, - const s8 pattern_type, const s8 end_type, - const char *function) + const s8 pattern_type, const s8 end_type) { const char *const start = filename; bool in_repetition = false; @@ -194,7 +192,6 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type, unsigned char c; unsigned char d; unsigned char e; - const char *original_filename = filename; if (!filename) goto out; @@ -283,25 +280,20 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type, goto out; return true; out: - printk(KERN_DEBUG "%s: Invalid pathname '%s'\n", function, - original_filename); return false; } /** * tomoyo_is_correct_domain - Check whether the given domainname follows the naming rules. * @domainname: The domainname to check. - * @function: The name of function calling me. * * Returns true if @domainname follows the naming rules, false otherwise. */ -bool tomoyo_is_correct_domain(const unsigned char *domainname, - const char *function) +bool tomoyo_is_correct_domain(const unsigned char *domainname) { unsigned char c; unsigned char d; unsigned char e; - const char *org_domainname = domainname; if (!domainname || strncmp(domainname, TOMOYO_ROOT_NAME, TOMOYO_ROOT_NAME_LEN)) @@ -344,8 +336,6 @@ bool tomoyo_is_correct_domain(const unsigned char *domainname, } while (*domainname); return true; out: - printk(KERN_DEBUG "%s: Invalid domainname '%s'\n", function, - org_domainname); return false; } @@ -1086,11 +1076,11 @@ static int tomoyo_update_manager_entry(const char *manager, bool is_domain = false; if (tomoyo_is_domain_def(manager)) { - if (!tomoyo_is_correct_domain(manager, __func__)) + if (!tomoyo_is_correct_domain(manager)) return -EINVAL; is_domain = true; } else { - if (!tomoyo_is_correct_path(manager, 1, -1, -1, __func__)) + if (!tomoyo_is_correct_path(manager, 1, -1, -1)) return -EINVAL; } saved_manager = tomoyo_get_name(manager); diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 17ed365..67bd22d 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -520,12 +520,10 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain); bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); /* Check whether the domainname is correct. */ -bool tomoyo_is_correct_domain(const unsigned char *domainname, - const char *function); +bool tomoyo_is_correct_domain(const unsigned char *domainname); /* Check whether the token is correct. */ bool tomoyo_is_correct_path(const char *filename, const s8 start_type, - const s8 pattern_type, const s8 end_type, - const char *function); + const s8 pattern_type, const s8 end_type); /* Check whether the token can be a domainname. */ bool tomoyo_is_domain_def(const unsigned char *buffer); /* Check whether the given filename matches the given pattern. */ diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 74cd0f5..66caaa1 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -136,13 +136,13 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, int error = is_delete ? -ENOENT : -ENOMEM; bool is_last_name = false; - if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__)) + if (!tomoyo_is_correct_path(program, 1, -1, -1)) return -EINVAL; /* No patterns allowed. */ if (domainname) { if (!tomoyo_is_domain_def(domainname) && - tomoyo_is_correct_path(domainname, 1, -1, -1, __func__)) + tomoyo_is_correct_path(domainname, 1, -1, -1)) is_last_name = true; - else if (!tomoyo_is_correct_domain(domainname, __func__)) + else if (!tomoyo_is_correct_domain(domainname)) return -EINVAL; saved_domainname = tomoyo_get_name(domainname); if (!saved_domainname) @@ -357,12 +357,12 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, bool is_last_name = false; if (!tomoyo_is_domain_def(domainname) && - tomoyo_is_correct_path(domainname, 1, -1, -1, __func__)) + tomoyo_is_correct_path(domainname, 1, -1, -1)) is_last_name = true; - else if (!tomoyo_is_correct_domain(domainname, __func__)) + else if (!tomoyo_is_correct_domain(domainname)) return -EINVAL; if (program) { - if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__)) + if (!tomoyo_is_correct_path(program, 1, -1, -1)) return -EINVAL; saved_program = tomoyo_get_name(program); if (!saved_program) @@ -556,8 +556,8 @@ static int tomoyo_update_alias_entry(const char *original_name, const struct tomoyo_path_info *saved_aliased_name; int error = is_delete ? -ENOENT : -ENOMEM; - if (!tomoyo_is_correct_path(original_name, 1, -1, -1, __func__) || - !tomoyo_is_correct_path(aliased_name, 1, -1, -1, __func__)) + if (!tomoyo_is_correct_path(original_name, 1, -1, -1) || + !tomoyo_is_correct_path(aliased_name, 1, -1, -1)) return -EINVAL; /* No patterns allowed. */ saved_original_name = tomoyo_get_name(original_name); saved_aliased_name = tomoyo_get_name(aliased_name); @@ -659,7 +659,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * const struct tomoyo_path_info *saved_domainname; bool found = false; - if (!tomoyo_is_correct_domain(domainname, __func__)) + if (!tomoyo_is_correct_domain(domainname)) return NULL; saved_domainname = tomoyo_get_name(domainname); if (!saved_domainname) diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index db342ef..1b24304 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -168,7 +168,7 @@ static int tomoyo_update_globally_readable_entry(const char *filename, const struct tomoyo_path_info *saved_filename; int error = is_delete ? -ENOENT : -ENOMEM; - if (!tomoyo_is_correct_path(filename, 1, 0, -1, __func__)) + if (!tomoyo_is_correct_path(filename, 1, 0, -1)) return -EINVAL; saved_filename = tomoyo_get_name(filename); if (!saved_filename) @@ -468,7 +468,7 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, const struct tomoyo_path_info *saved_pattern; int error = is_delete ? -ENOENT : -ENOMEM; - if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__)) + if (!tomoyo_is_correct_path(pattern, 0, 0, 0)) return -EINVAL; saved_pattern = tomoyo_get_name(pattern); if (!saved_pattern) @@ -814,7 +814,7 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename, if (!domain) return -EINVAL; - if (!tomoyo_is_correct_path(filename, 0, 0, 0, __func__)) + if (!tomoyo_is_correct_path(filename, 0, 0, 0)) return -EINVAL; saved_filename = tomoyo_get_name(filename); if (!saved_filename) @@ -898,8 +898,8 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1, if (!domain) return -EINVAL; - if (!tomoyo_is_correct_path(filename1, 0, 0, 0, __func__) || - !tomoyo_is_correct_path(filename2, 0, 0, 0, __func__)) + if (!tomoyo_is_correct_path(filename1, 0, 0, 0) || + !tomoyo_is_correct_path(filename2, 0, 0, 0)) return -EINVAL; saved_filename1 = tomoyo_get_name(filename1); saved_filename2 = tomoyo_get_name(filename2); -- cgit v1.1 From 1fcdc7c527010b144d3951f9ce25faedf264933c Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Thu, 25 Feb 2010 17:19:25 +0900 Subject: TOMOYO: Protect find_task_by_vpid() with RCU. Holding tasklist_lock is no longer sufficient for find_task_by_vpid(). Explicit rcu_read_lock() is required. Signed-off-by: Tetsuo Handa -- security/tomoyo/common.c | 4 ++++ 1 file changed, 4 insertions(+) Signed-off-by: James Morris --- security/tomoyo/common.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'security/tomoyo') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 30dd1c6..ff51f10 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -1232,11 +1232,13 @@ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head, if (sscanf(data, "pid=%u", &pid) == 1) { struct task_struct *p; + rcu_read_lock(); read_lock(&tasklist_lock); p = find_task_by_vpid(pid); if (p) domain = tomoyo_real_domain(p); read_unlock(&tasklist_lock); + rcu_read_unlock(); } else if (!strncmp(data, "domain=", 7)) { if (tomoyo_is_domain_def(data + 7)) domain = tomoyo_find_domain(data + 7); @@ -1635,11 +1637,13 @@ static int tomoyo_read_pid(struct tomoyo_io_buffer *head) const int pid = head->read_step; struct task_struct *p; struct tomoyo_domain_info *domain = NULL; + rcu_read_lock(); read_lock(&tasklist_lock); p = find_task_by_vpid(pid); if (p) domain = tomoyo_real_domain(p); read_unlock(&tasklist_lock); + rcu_read_unlock(); if (domain) tomoyo_io_printf(head, "%d %u %s", pid, domain->profile, domain->domainname->name); -- cgit v1.1