diff options
Diffstat (limited to 'security/tomoyo/memory.c')
| -rw-r--r-- | security/tomoyo/memory.c | 183 | 
1 files changed, 51 insertions, 132 deletions
diff --git a/security/tomoyo/memory.c b/security/tomoyo/memory.c index 297612669c7..0e995716cc2 100644 --- a/security/tomoyo/memory.c +++ b/security/tomoyo/memory.c @@ -1,9 +1,7 @@  /*   * security/tomoyo/memory.c   * - * Memory management functions for TOMOYO. - * - * Copyright (C) 2005-2010  NTT DATA CORPORATION + * Copyright (C) 2005-2011  NTT DATA CORPORATION   */  #include <linux/hash.h> @@ -29,10 +27,10 @@ void tomoyo_warn_oom(const char *function)  		panic("MAC Initialization failed.\n");  } -/* Memory allocated for policy. */ -static atomic_t tomoyo_policy_memory_size; -/* Quota for holding policy. */ -static unsigned int tomoyo_quota_for_policy; +/* Memoy currently used by policy/audit log/query. */ +unsigned int tomoyo_memory_used[TOMOYO_MAX_MEMORY_STAT]; +/* Memory quota for "policy"/"audit log"/"query". */ +unsigned int tomoyo_memory_quota[TOMOYO_MAX_MEMORY_STAT];  /**   * tomoyo_memory_ok - Check memory quota. @@ -42,18 +40,20 @@ static unsigned int tomoyo_quota_for_policy;   * Returns true on success, false otherwise.   *   * Returns true if @ptr is not NULL and quota not exceeded, false otherwise. + * + * Caller holds tomoyo_policy_lock mutex.   */  bool tomoyo_memory_ok(void *ptr)  { -	size_t s = ptr ? ksize(ptr) : 0; -	atomic_add(s, &tomoyo_policy_memory_size); -	if (ptr && (!tomoyo_quota_for_policy || -		    atomic_read(&tomoyo_policy_memory_size) -		    <= tomoyo_quota_for_policy)) { -		memset(ptr, 0, s); -		return true; +	if (ptr) { +		const size_t s = ksize(ptr); +		tomoyo_memory_used[TOMOYO_MEMORY_POLICY] += s; +		if (!tomoyo_memory_quota[TOMOYO_MEMORY_POLICY] || +		    tomoyo_memory_used[TOMOYO_MEMORY_POLICY] <= +		    tomoyo_memory_quota[TOMOYO_MEMORY_POLICY]) +			return true; +		tomoyo_memory_used[TOMOYO_MEMORY_POLICY] -= s;  	} -	atomic_sub(s, &tomoyo_policy_memory_size);  	tomoyo_warn_oom(__func__);  	return false;  } @@ -66,6 +66,8 @@ bool tomoyo_memory_ok(void *ptr)   *   * Returns pointer to allocated memory on success, NULL otherwise.   * @data is zero-cleared on success. + * + * Caller holds tomoyo_policy_lock mutex.   */  void *tomoyo_commit_ok(void *data, const unsigned int size)  { @@ -75,32 +77,25 @@ void *tomoyo_commit_ok(void *data, const unsigned int size)  		memset(data, 0, size);  		return ptr;  	} -	return NULL; -} - -/** - * 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); +	return NULL;  }  /**   * tomoyo_get_group - Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group".   * - * @group_name: The name of address group. - * @idx:        Index number. + * @param: Pointer to "struct tomoyo_acl_param". + * @idx:   Index number.   *   * Returns pointer to "struct tomoyo_group" on success, NULL otherwise.   */ -struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx) +struct tomoyo_group *tomoyo_get_group(struct tomoyo_acl_param *param, +				      const u8 idx)  {  	struct tomoyo_group e = { };  	struct tomoyo_group *group = NULL; +	struct list_head *list; +	const char *group_name = tomoyo_read_token(param);  	bool found = false;  	if (!tomoyo_correct_word(group_name) || idx >= TOMOYO_MAX_GROUP)  		return NULL; @@ -109,10 +104,12 @@ struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx)  		return NULL;  	if (mutex_lock_interruptible(&tomoyo_policy_lock))  		goto out; -	list_for_each_entry(group, &tomoyo_group_list[idx], list) { -		if (e.group_name != group->group_name) +	list = ¶m->ns->group_list[idx]; +	list_for_each_entry(group, list, head.list) { +		if (e.group_name != group->group_name || +		    atomic_read(&group->head.users) == TOMOYO_GC_IN_PROGRESS)  			continue; -		atomic_inc(&group->users); +		atomic_inc(&group->head.users);  		found = true;  		break;  	} @@ -120,15 +117,14 @@ struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx)  		struct tomoyo_group *entry = tomoyo_commit_ok(&e, sizeof(e));  		if (entry) {  			INIT_LIST_HEAD(&entry->member_list); -			atomic_set(&entry->users, 1); -			list_add_tail_rcu(&entry->list, -					  &tomoyo_group_list[idx]); +			atomic_set(&entry->head.users, 1); +			list_add_tail_rcu(&entry->head.list, list);  			group = entry;  			found = true;  		}  	}  	mutex_unlock(&tomoyo_policy_lock); - out: +out:  	tomoyo_put_name(e.group_name);  	return found ? group : NULL;  } @@ -153,7 +149,6 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name)  	struct tomoyo_name *ptr;  	unsigned int hash;  	int len; -	int allocated_len;  	struct list_head *head;  	if (!name) @@ -163,120 +158,44 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name)  	head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)];  	if (mutex_lock_interruptible(&tomoyo_policy_lock))  		return NULL; -	list_for_each_entry(ptr, head, list) { -		if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name)) +	list_for_each_entry(ptr, head, head.list) { +		if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name) || +		    atomic_read(&ptr->head.users) == TOMOYO_GC_IN_PROGRESS)  			continue; -		atomic_inc(&ptr->users); +		atomic_inc(&ptr->head.users);  		goto out;  	}  	ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS); -	allocated_len = ptr ? ksize(ptr) : 0; -	if (!ptr || (tomoyo_quota_for_policy && -		     atomic_read(&tomoyo_policy_memory_size) + allocated_len -		     > tomoyo_quota_for_policy)) { +	if (tomoyo_memory_ok(ptr)) { +		ptr->entry.name = ((char *) ptr) + sizeof(*ptr); +		memmove((char *) ptr->entry.name, name, len); +		atomic_set(&ptr->head.users, 1); +		tomoyo_fill_path_info(&ptr->entry); +		list_add_tail(&ptr->head.list, head); +	} else {  		kfree(ptr);  		ptr = NULL; -		tomoyo_warn_oom(__func__); -		goto out;  	} -	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: +out:  	mutex_unlock(&tomoyo_policy_lock);  	return ptr ? &ptr->entry : NULL;  } +/* Initial namespace.*/ +struct tomoyo_policy_namespace tomoyo_kernel_namespace; +  /**   * tomoyo_mm_init - Initialize mm related code.   */  void __init tomoyo_mm_init(void)  {  	int idx; - -	for (idx = 0; idx < TOMOYO_MAX_POLICY; idx++) -		INIT_LIST_HEAD(&tomoyo_policy_list[idx]); -	for (idx = 0; idx < TOMOYO_MAX_GROUP; idx++) -		INIT_LIST_HEAD(&tomoyo_group_list[idx]);  	for (idx = 0; idx < TOMOYO_MAX_HASH; idx++)  		INIT_LIST_HEAD(&tomoyo_name_list[idx]); +	tomoyo_kernel_namespace.name = "<kernel>"; +	tomoyo_init_policy_namespace(&tomoyo_kernel_namespace); +	tomoyo_kernel_domain.ns = &tomoyo_kernel_namespace;  	INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list); -	tomoyo_kernel_domain.domainname = tomoyo_get_name(TOMOYO_ROOT_NAME); +	tomoyo_kernel_domain.domainname = tomoyo_get_name("<kernel>");  	list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list); -	idx = tomoyo_read_lock(); -	if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain) -		panic("Can't register tomoyo_kernel_domain"); -	{ -		/* Load built-in policy. */ -		tomoyo_write_transition_control("/sbin/hotplug", false, -					TOMOYO_TRANSITION_CONTROL_INITIALIZE); -		tomoyo_write_transition_control("/sbin/modprobe", false, -					TOMOYO_TRANSITION_CONTROL_INITIALIZE); -	} -	tomoyo_read_unlock(idx); -} - - -/* Memory allocated for query lists. */ -unsigned int tomoyo_query_memory_size; -/* Quota for holding query lists. */ -unsigned int tomoyo_quota_for_query; - -/** - * tomoyo_read_memory_counter - Check for memory usage in bytes. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * - * Returns memory usage. - */ -void tomoyo_read_memory_counter(struct tomoyo_io_buffer *head) -{ -	if (!head->r.eof) { -		const unsigned int policy -			= atomic_read(&tomoyo_policy_memory_size); -		const unsigned int query = tomoyo_query_memory_size; -		char buffer[64]; - -		memset(buffer, 0, sizeof(buffer)); -		if (tomoyo_quota_for_policy) -			snprintf(buffer, sizeof(buffer) - 1, -				 "   (Quota: %10u)", -				 tomoyo_quota_for_policy); -		else -			buffer[0] = '\0'; -		tomoyo_io_printf(head, "Policy:       %10u%s\n", policy, -				 buffer); -		if (tomoyo_quota_for_query) -			snprintf(buffer, sizeof(buffer) - 1, -				 "   (Quota: %10u)", -				 tomoyo_quota_for_query); -		else -			buffer[0] = '\0'; -		tomoyo_io_printf(head, "Query lists:  %10u%s\n", query, -				 buffer); -		tomoyo_io_printf(head, "Total:        %10u\n", policy + query); -		head->r.eof = true; -	} -} - -/** - * tomoyo_write_memory_quota - Set memory quota. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * - * Returns 0. - */ -int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head) -{ -	char *data = head->write_buf; -	unsigned int size; - -	if (sscanf(data, "Policy: %u", &size) == 1) -		tomoyo_quota_for_policy = size; -	else if (sscanf(data, "Query lists: %u", &size) == 1) -		tomoyo_quota_for_query = size; -	return 0;  }  | 
