This patch contains code for checking non-posix capability. TOMOYO is ready to support 65536 types of non-posix capabilities. But I can't utilize TOMOYO's ability because (1) Hooks are missing. or (2) Posix's capability and functionality are not one to one mapping. Therefore I can't derive functionality the caller wants to use from posix's capability number (e.g. CAP_SYS_ADMIN). or (3) Hooks are provided but it is not permitted to sleep (e.g. CAP_SYS_NICE) while TOMOYO needs hooks where it is permitted to sleep. or (4) System calls and device drivers use the same posix's capability number. Thus whether MAC's policy suits or not depends on hardware the system is running. TOMOYO wants to distinguish requests from userland applications and requests from kernel drivers, but I can't distinguish it from posix's capability number. Therefore, LSM version of TOMOYO has very poor support compared to non-LSM version of TOMOYO. I hope this problem is solved in the future. Signed-off-by: Tetsuo Handa --- security/tomoyo/capability.c | 141 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) --- /dev/null +++ security-testing-2.6/security/tomoyo/capability.c @@ -0,0 +1,141 @@ +/* + * security/tomoyo/capability.c + * + * Copyright (C) 2005-2009 NTT DATA CORPORATION + */ +#include "internal.h" + +/** + * tomoyo_audit_capability_log - Audit capability log. + * + * @r: Pointer to "struct tomoyo_request_info". + * @operation: Type of operation. + * @is_granted: True if this is a granted log. + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_audit_capability_log(struct tomoyo_request_info *r, + const u8 operation, + const bool is_granted) +{ + if (!is_granted) + tomoyo_warn_log(r, "capability %s", + tomoyo_cap2keyword(operation)); + return tomoyo_write_audit_log(is_granted, r, + TOMOYO_KEYWORD_ALLOW_CAPABILITY "%s\n", + tomoyo_cap2keyword(operation)); +} + +/** + * tomoyo_capable - Check permission for capability. + * + * @operation: Type of operation. + * + * Returns true on success, false otherwise. + * + * Caller holds tomoyo_read_lock(). + */ +static bool tomoyo_capable2(const u8 operation) +{ + struct tomoyo_request_info r; + struct tomoyo_acl_info *ptr; + int error; + if (tomoyo_init_request_info(&r, NULL, TOMOYO_MAX_MAC_INDEX + + operation) == TOMOYO_CONFIG_DISABLED) + return true; + do { + error = -EPERM; + list_for_each_entry_rcu(ptr, &r.domain->acl_info_list, list) { + struct tomoyo_capability_acl *acl; + if (ptr->is_deleted || + ptr->type != TOMOYO_TYPE_CAPABILITY_ACL) + continue; + acl = container_of(ptr, struct tomoyo_capability_acl, + head); + if (acl->operation != operation || + !tomoyo_condition(&r, ptr)) + continue; + r.cond = ptr->cond; + error = 0; + break; + } + tomoyo_audit_capability_log(&r, operation, !error); + if (!error) + break; + error = tomoyo_supervisor(&r, TOMOYO_KEYWORD_ALLOW_CAPABILITY + "%s\n", + tomoyo_cap2keyword(operation)); + } while (error == 1); + return !error; +} + +/** + * tomoyo_capable - Check permission for capability. + * + * @operation: Type of operation. + * + * Returns true on success, false otherwise. + */ +bool tomoyo_capable(const u8 operation) +{ + const int idx = tomoyo_read_lock(); + const int error = tomoyo_capable2(operation); + tomoyo_read_unlock(idx); + return error; +} + +/** + * tomoyo_write_capability_policy - Write "struct tomoyo_capability_acl" list. + * + * @data: String to parse. + * @domain: Pointer to "struct tomoyo_domain_info". + * @condition: Pointer to "struct tomoyo_condition". May be NULL. + * @is_delete: True if it is a delete request. + * + * Returns 0 on success, negative value otherwise. + */ +int tomoyo_write_capability_policy(char *data, + struct tomoyo_domain_info *domain, + struct tomoyo_condition *condition, + const bool is_delete) +{ + struct tomoyo_capability_acl e = { + .head.type = TOMOYO_TYPE_CAPABILITY_ACL, + .head.cond = condition, + }; + struct tomoyo_capability_acl *entry = NULL; + struct tomoyo_acl_info *ptr; + int error = is_delete ? -ENOENT : -ENOMEM; + u8 capability; + for (capability = 0; capability < TOMOYO_MAX_CAPABILITY_INDEX; + capability++) { + if (strcmp(data, tomoyo_cap2keyword(capability))) + continue; + break; + } + if (capability == TOMOYO_MAX_CAPABILITY_INDEX) + return -EINVAL; + e.operation = capability; + if (!is_delete) + entry = kmalloc(sizeof(e), GFP_KERNEL); + mutex_lock(&tomoyo_policy_lock); + list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { + struct tomoyo_capability_acl *acl = + container_of(ptr, struct tomoyo_capability_acl, + head); + if (ptr->type != TOMOYO_TYPE_CAPABILITY_ACL || + ptr->cond != condition || acl->operation != capability) + continue; + ptr->is_deleted = is_delete; + error = 0; + break; + } + if (!is_delete && error && tomoyo_commit_ok(entry, &e, sizeof(e))) { + tomoyo_add_domain_acl(domain, &entry->head); + entry = NULL; + error = 0; + } + mutex_unlock(&tomoyo_policy_lock); + kfree(entry); + return error; +} -- -- 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/