From 8c6cb983cd52d78ab4e4c0191c73a11dcb60b866 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Sat, 19 Jan 2019 23:11:40 +0900 Subject: tomoyo: Swicth from cred->security to task_struct->security. TOMOYO security module is designed to use "struct task_struct"->security in order to allow per "struct task_struct" tracking without being disturbed by unable to update "struct cred"->security due to override mechanism. Now that infrastructure-managed security blob is ready, this patch updates TOMOYO to use "struct task_struct"->security. Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/tomoyo.c | 149 +++++++++++++++++++++++++---------------------- 1 file changed, 79 insertions(+), 70 deletions(-) (limited to 'security/tomoyo/tomoyo.c') diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 2b3eee06004b..c2ab6575e68e 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -9,19 +9,19 @@ #include "common.h" /** - * tomoyo_cred_alloc_blank - Target for security_cred_alloc_blank(). + * tomoyo_domain - Get "struct tomoyo_domain_info" for current thread. * - * @new: Pointer to "struct cred". - * @gfp: Memory allocation flags. - * - * Returns 0. + * Returns pointer to "struct tomoyo_domain_info" for current thread. */ -static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp) +struct tomoyo_domain_info *tomoyo_domain(void) { - struct tomoyo_domain_info **blob = tomoyo_cred(new); + struct tomoyo_task *s = tomoyo_task(current); - *blob = NULL; - return 0; + if (s->old_domain_info && !current->in_execve) { + atomic_dec(&s->old_domain_info->users); + s->old_domain_info = NULL; + } + return s->domain_info; } /** @@ -36,85 +36,56 @@ 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) { - struct tomoyo_domain_info **old_blob = tomoyo_cred(old); - struct tomoyo_domain_info **new_blob = tomoyo_cred(new); - struct tomoyo_domain_info *domain; - - domain = *old_blob; - *new_blob = domain; + /* Restore old_domain_info saved by previous execve() request. */ + struct tomoyo_task *s = tomoyo_task(current); - if (domain) - atomic_inc(&domain->users); + if (s->old_domain_info && !current->in_execve) { + atomic_dec(&s->domain_info->users); + s->domain_info = s->old_domain_info; + s->old_domain_info = NULL; + } return 0; } /** - * tomoyo_cred_transfer - Target for security_transfer_creds(). + * tomoyo_bprm_committed_creds - Target for security_bprm_committed_creds(). * - * @new: Pointer to "struct cred". - * @old: Pointer to "struct cred". - */ -static void tomoyo_cred_transfer(struct cred *new, const struct cred *old) -{ - tomoyo_cred_prepare(new, old, 0); -} - -/** - * tomoyo_cred_free - Target for security_cred_free(). - * - * @cred: Pointer to "struct cred". + * @bprm: Pointer to "struct linux_binprm". */ -static void tomoyo_cred_free(struct cred *cred) +static void tomoyo_bprm_committed_creds(struct linux_binprm *bprm) { - struct tomoyo_domain_info **blob = tomoyo_cred(cred); - struct tomoyo_domain_info *domain = *blob; + /* Clear old_domain_info saved by execve() request. */ + struct tomoyo_task *s = tomoyo_task(current); - if (domain) - atomic_dec(&domain->users); + atomic_dec(&s->old_domain_info->users); + s->old_domain_info = NULL; } +#ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER /** * tomoyo_bprm_set_creds - Target for security_bprm_set_creds(). * * @bprm: Pointer to "struct linux_binprm". * - * Returns 0 on success, negative value otherwise. + * Returns 0. */ static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) { - struct tomoyo_domain_info **blob; - struct tomoyo_domain_info *domain; - /* * Do only if this function is called for the first time of an execve * operation. */ if (bprm->called_set_creds) return 0; -#ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER /* * Load policy if /sbin/tomoyo-init exists and /sbin/init is requested * for the first time. */ if (!tomoyo_policy_loaded) tomoyo_load_policy(bprm->filename); -#endif - /* - * 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(). - */ - blob = tomoyo_cred(bprm->cred); - domain = *blob; - atomic_dec(&domain->users); - /* - * Tell tomoyo_bprm_check_security() is called for the first time of an - * execve operation. - */ - *blob = NULL; return 0; } +#endif /** * tomoyo_bprm_check_security - Target for security_bprm_check(). @@ -125,16 +96,13 @@ static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) */ static int tomoyo_bprm_check_security(struct linux_binprm *bprm) { - struct tomoyo_domain_info **blob; - struct tomoyo_domain_info *domain; + struct tomoyo_task *s = tomoyo_task(current); - blob = tomoyo_cred(bprm->cred); - domain = *blob; /* * Execute permission is checked against pathname passed to do_execve() * using current domain. */ - if (!domain) { + if (!s->old_domain_info) { const int idx = tomoyo_read_lock(); const int err = tomoyo_find_next_domain(bprm); tomoyo_read_unlock(idx); @@ -143,8 +111,8 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm) /* * Read permission is checked against interpreters using next domain. */ - return tomoyo_check_open_permission(domain, &bprm->file->f_path, - O_RDONLY); + return tomoyo_check_open_permission(s->domain_info, + &bprm->file->f_path, O_RDONLY); } /** @@ -510,19 +478,60 @@ static int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg, } struct lsm_blob_sizes tomoyo_blob_sizes __lsm_ro_after_init = { - .lbs_cred = sizeof(struct tomoyo_domain_info *), + .lbs_task = sizeof(struct tomoyo_task), }; +/** + * tomoyo_task_alloc - Target for security_task_alloc(). + * + * @task: Pointer to "struct task_struct". + * @flags: clone() flags. + * + * Returns 0. + */ +static int tomoyo_task_alloc(struct task_struct *task, + unsigned long clone_flags) +{ + struct tomoyo_task *old = tomoyo_task(current); + struct tomoyo_task *new = tomoyo_task(task); + + new->domain_info = old->domain_info; + atomic_inc(&new->domain_info->users); + new->old_domain_info = NULL; + return 0; +} + +/** + * tomoyo_task_free - Target for security_task_free(). + * + * @task: Pointer to "struct task_struct". + */ +static void tomoyo_task_free(struct task_struct *task) +{ + struct tomoyo_task *s = tomoyo_task(task); + + if (s->domain_info) { + atomic_dec(&s->domain_info->users); + s->domain_info = NULL; + } + if (s->old_domain_info) { + atomic_dec(&s->old_domain_info->users); + s->old_domain_info = NULL; + } +} + /* * tomoyo_security_ops is a "struct security_operations" which is used for * registering TOMOYO. */ static struct security_hook_list tomoyo_hooks[] __lsm_ro_after_init = { - LSM_HOOK_INIT(cred_alloc_blank, tomoyo_cred_alloc_blank), LSM_HOOK_INIT(cred_prepare, tomoyo_cred_prepare), - LSM_HOOK_INIT(cred_transfer, tomoyo_cred_transfer), - LSM_HOOK_INIT(cred_free, tomoyo_cred_free), + LSM_HOOK_INIT(bprm_committed_creds, tomoyo_bprm_committed_creds), + LSM_HOOK_INIT(task_alloc, tomoyo_task_alloc), + LSM_HOOK_INIT(task_free, tomoyo_task_free), +#ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER LSM_HOOK_INIT(bprm_set_creds, tomoyo_bprm_set_creds), +#endif LSM_HOOK_INIT(bprm_check_security, tomoyo_bprm_check_security), LSM_HOOK_INIT(file_fcntl, tomoyo_file_fcntl), LSM_HOOK_INIT(file_open, tomoyo_file_open), @@ -560,14 +569,14 @@ int tomoyo_enabled __lsm_ro_after_init = 1; */ static int __init tomoyo_init(void) { - struct cred *cred = (struct cred *) current_cred(); - struct tomoyo_domain_info **blob; + struct tomoyo_task *s = tomoyo_task(current); /* register ourselves with the security framework */ security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), "tomoyo"); printk(KERN_INFO "TOMOYO Linux initialized\n"); - blob = tomoyo_cred(cred); - *blob = &tomoyo_kernel_domain; + s->domain_info = &tomoyo_kernel_domain; + atomic_inc(&tomoyo_kernel_domain.users); + s->old_domain_info = NULL; tomoyo_mm_init(); return 0; -- cgit v1.2.3