Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933140AbXHXMyU (ORCPT ); Fri, 24 Aug 2007 08:54:20 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S933013AbXHXMx4 (ORCPT ); Fri, 24 Aug 2007 08:53:56 -0400 Received: from rv-out-0910.google.com ([209.85.198.190]:8087 "EHLO rv-out-0910.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933001AbXHXMxw (ORCPT ); Fri, 24 Aug 2007 08:53:52 -0400 DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=beta; h=received:message-id:date:from:user-agent:mime-version:to:subject:references:in-reply-to:content-type:content-transfer-encoding; b=btPGNWC1l4wwE2zWJ3kWJMVLY+Sq7DKt7dIz+KlEkqHmcDKvlCuH+xOmcT8mDbAIhb56X76Fl57zZPG71RcAoyUZ/3VN966EbEPuEO6ItzNyhh7QYUL6HcaPBlCd9i24WeSWkjf1Vwbucqfj7d16wlWJQ8z138Qd6nEYvaoMGNk= Message-ID: <46CED4DC.5040405@gmail.com> Date: Fri, 24 Aug 2007 21:53:48 +0900 From: Kentaro Takeda User-Agent: Thunderbird 2.0.0.6 (Windows/20070728) MIME-Version: 1.0 To: linux-kernel@vger.kernel.org, linux-security-module@vger.kernel.org, chrisw@sous-sol.org Subject: [TOMOYO 09/15] Argv[0] access control functions. References: <46CED214.6050505@gmail.com> In-Reply-To: <46CED214.6050505@gmail.com> Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6248 Lines: 252 argv[0] check functions for TOMOYO Linux. If the executed program name and argv[0] is different, TOMOYO Linux checks permission. Each permission can be automatically accumulated into the policy of each domain using 'learning mode'. Signed-off-by: Kentaro Takeda Signed-off-by: Tetsuo Handa --- security/tomoyo/exec.c | 230 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 230 insertions(+) --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6/security/tomoyo/exec.c 2007-08-24 15:51:37.000000000 +0900 @@ -0,0 +1,230 @@ +/* + * security/tomoyo/exec.c + * + * Argv0 access control functions for TOMOYO Linux. + */ + +#include "tomoyo.h" +#include "realpath.h" + +/************************* AUDIT FUNCTIONS *************************/ + +static int tmy_audit_argv0_log(const struct path_info *filename, + const char *argv0, + const int is_granted, + const int is_enforce) +{ + char *buf; + int len; + + if (is_granted) { + if (!tmy_audit_grant()) + return 0; + } else { + if (!tmy_audit_reject()) + return 0; + } + + len = filename->total_len + strlen(argv0) + 8; + buf = tmy_init_audit_log(&len); + + if (!buf) + return -ENOMEM; + + snprintf(buf + strlen(buf), + len - strlen(buf) - 1, + TMY_ALLOW_ARGV0 "%s %s", + filename->name, + argv0); + + return tmy_write_audit_log(buf, is_granted, is_enforce); +} + +/************************* ARGV0 MISMATCH HANDLER *************************/ + +/* + * @is_add: 1 add this entry if not quota exceeded + * -1 always add this entry + * 0 remove this entry + */ +static int tmy_add_argv0_entry(const char *filename, + const char *argv0, + struct domain_info *domain, + const struct condition_list *cond, + const u8 is_add) +{ + struct acl_info *ptr; + const struct path_info *saved_filename; + const struct path_info *saved_argv0; + int error = -ENOMEM; + + if (!tmy_correct_path(filename, 1, 0, -1, __FUNCTION__) || + !tmy_correct_path(argv0, -1, 0, -1, __FUNCTION__) || + strchr(argv0, '/')) + return -EINVAL; + + saved_filename = tmy_save_name(filename); + saved_argv0 = tmy_save_name(argv0); + if (!saved_filename || !saved_argv0) + return -ENOMEM; + + down(&domain_acl_lock); + + if (!is_add) + goto remove; + + ptr = domain->first_acl_ptr; + if (!ptr) + goto first_entry; + while (1) { + struct argv0_acl *acl = (struct argv0_acl *) ptr; + + if (ptr->type == TMY_TYPE_ARGV0_ACL && ptr->cond == cond && + acl->filename == saved_filename && + acl->argv0 == saved_argv0) { + ptr->is_deleted = 0; + /* Found. Nothing to do. */ + error = 0; + break; + } + + if (ptr->next) { + ptr = ptr->next; + continue; + } + +first_entry: ; + if (is_add == 1 && tmy_too_many_acl(domain)) + break; + + /* Not found. Append it to the tail. */ + acl = tmy_alloc_element(sizeof(*acl)); + if (!acl) + break; + + acl->head.type = TMY_TYPE_ARGV0_ACL; + acl->head.cond = cond; + acl->filename = saved_filename; + acl->argv0 = saved_argv0; + error = tmy_add_acl(ptr, domain, + (struct acl_info *) acl); + + break; + } + goto ok; +remove: ; + error = -ENOENT; + for (ptr = domain->first_acl_ptr; ptr; ptr = ptr->next) { + struct argv0_acl *acl = (struct argv0_acl *) ptr; + + if (ptr->type != TMY_TYPE_ARGV0_ACL || + ptr->cond != cond || ptr->is_deleted || + acl->filename != saved_filename || + acl->argv0 != saved_argv0) + continue; + + error = tmy_del_acl(ptr); + break; + } +ok: ; + up(&domain_acl_lock); + + return error; +} + +static int tmy_argv0_acl(const struct path_info *filename, + const char *argv0_) +{ + const struct domain_info *domain = TMY_SECURITY->domain; + int error = -EPERM; + struct acl_info *ptr; + struct path_info argv0; + + if (!tmy_flags(TMY_MAC_FOR_ARGV0)) + return 0; + + argv0.name = argv0_; + tmy_fill_path_info(&argv0); + + for (ptr = domain->first_acl_ptr; ptr; ptr = ptr->next) { + struct argv0_acl *acl = (struct argv0_acl *) ptr; + + if (ptr->type == TMY_TYPE_ARGV0_ACL && + ptr->is_deleted == 0 && + tmy_check_condition(ptr->cond, NULL) == 0 && + tmy_path_match(filename, acl->filename) && + tmy_path_match(&argv0, acl->argv0)) { + error = 0; + break; + } + } + + return error; +} + +/** + * tmy_argv0_perm - check for argv[0] permission. + * @filename: pointer to filename. + * @argv0: pointer to basename of argv[0]. + * + * Returns zero if permission granted. + * Returns nonzero if permission denied. + */ +int tmy_argv0_perm(const struct path_info *filename, const char *argv0) +{ + int error = 0; + const int is_enforce = tmy_enforce(TMY_MAC_FOR_ARGV0); + + if (!tmy_flags(TMY_MAC_FOR_ARGV0)) + return 0; + if (!filename || !argv0 || !*argv0) + return 0; + + error = tmy_argv0_acl(filename, argv0); + + tmy_audit_argv0_log(filename, argv0, !error, is_enforce); + + if (error) { + struct domain_info * const domain = TMY_SECURITY->domain; + + if (is_enforce) + error = tmy_supervisor("%s\n" TMY_ALLOW_ARGV0 "%s %s\n", + domain->domainname->name, + filename->name, argv0); + + else if (tmy_accept(TMY_MAC_FOR_ARGV0)) + tmy_add_argv0_entry(filename->name, argv0, domain, + NULL, 1); + + if (!is_enforce) + error = 0; + } + + return error; +} + +/** + * tmy_add_argv0_policy - add or delete argv[0] policy. + * @data: a line to parse. + * @domain: pointer to "struct domain_info". + * @cond: pointer to "struct condition_list". May be NULL. + * @is_delete: is this delete request? + * + * Returns zero on success. + * Returns nonzero on failure. + */ +int tmy_add_argv0_policy(char *data, + struct domain_info *domain, + const struct condition_list *cond, + const int is_delete) +{ + char *argv0 = strchr(data, ' '); + + if (!argv0) + return -EINVAL; + + *argv0++ = '\0'; + + return tmy_add_argv0_entry(data, argv0, domain, cond, + is_delete ? 0 : -1); +} - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/