forked from mirrors/linux
		
	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 <penguin-kernel@I-love.SAKURA.ne.jp> Acked-by: Serge Hallyn <serue@us.ibm.com> Signed-off-by: James Morris <jmorris@namei.org>
This commit is contained in:
		
							parent
							
								
									ec8e6a4e06
								
							
						
					
					
						commit
						847b173ea3
					
				
					 7 changed files with 436 additions and 54 deletions
				
			
		| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1067,7 +1067,7 @@ static int tomoyo_read_profile(struct tomoyo_io_buffer *head)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * # cat /sys/kernel/security/tomoyo/manager
 | 
					 * # 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.
 | 
					 * 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)
 | 
					static int tomoyo_close_control(struct file *file)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct tomoyo_io_buffer *head = file->private_data;
 | 
						struct tomoyo_io_buffer *head = file->private_data;
 | 
				
			||||||
 | 
						const bool is_write = !!head->write_buf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tomoyo_read_unlock(head->reader_idx);
 | 
						tomoyo_read_unlock(head->reader_idx);
 | 
				
			||||||
	/* Release memory used for policy I/O. */
 | 
						/* Release memory used for policy I/O. */
 | 
				
			||||||
| 
						 | 
					@ -2119,6 +2120,8 @@ static int tomoyo_close_control(struct file *file)
 | 
				
			||||||
	kfree(head);
 | 
						kfree(head);
 | 
				
			||||||
	head = NULL;
 | 
						head = NULL;
 | 
				
			||||||
	file->private_data = NULL;
 | 
						file->private_data = NULL;
 | 
				
			||||||
 | 
						if (is_write)
 | 
				
			||||||
 | 
							tomoyo_run_gc();
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -638,6 +638,11 @@ int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain,
 | 
				
			||||||
				    struct file *filp);
 | 
									    struct file *filp);
 | 
				
			||||||
int tomoyo_find_next_domain(struct linux_binprm *bprm);
 | 
					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. **********/
 | 
					/********** External variable definitions. **********/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Lock for GC. */
 | 
					/* Lock for GC. */
 | 
				
			||||||
| 
						 | 
					@ -646,6 +651,16 @@ extern struct srcu_struct tomoyo_ss;
 | 
				
			||||||
/* The list for "struct tomoyo_domain_info". */
 | 
					/* The list for "struct tomoyo_domain_info". */
 | 
				
			||||||
extern struct list_head tomoyo_domain_list;
 | 
					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. */
 | 
					/* Lock for protecting policy. */
 | 
				
			||||||
extern struct mutex tomoyo_policy_lock;
 | 
					extern struct mutex tomoyo_policy_lock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -110,7 +110,7 @@ const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain)
 | 
				
			||||||
 * will cause "/usr/sbin/httpd" to belong to "<kernel> /usr/sbin/httpd" domain
 | 
					 * will cause "/usr/sbin/httpd" to belong to "<kernel> /usr/sbin/httpd" domain
 | 
				
			||||||
 * unless executed from "<kernel> /etc/rc.d/init.d/httpd" domain.
 | 
					 * unless executed from "<kernel> /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.
 | 
					 * 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 *
 | 
				
			||||||
 * "<kernel> /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain, unless
 | 
					 * "<kernel> /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain, unless
 | 
				
			||||||
 * explicitly specified by "initialize_domain".
 | 
					 * 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.
 | 
					 * 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
 | 
					 * /bin/busybox and domainname which the current process will belong to after
 | 
				
			||||||
 * execve() succeeds is calculated using /bin/cat rather than /bin/busybox .
 | 
					 * 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.
 | 
					 * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
					 * given "allow_read /lib/libc-2.5.so" to the domain which current process
 | 
				
			||||||
 * belongs to.
 | 
					 * 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.
 | 
					 * 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
 | 
					 * which pretends as if /proc/self/ is not a symlink; so that we can forbid
 | 
				
			||||||
 * current process from accessing other process's information.
 | 
					 * 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.
 | 
					 * 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
 | 
					 * " (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.
 | 
					 * 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.
 | 
					 * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										370
									
								
								security/tomoyo/gc.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										370
									
								
								security/tomoyo/gc.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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 <linux/kthread.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -205,9 +205,9 @@ char *tomoyo_realpath_nofollow(const char *pathname)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Memory allocated for non-string data. */
 | 
					/* Memory allocated for non-string data. */
 | 
				
			||||||
static unsigned int tomoyo_allocated_memory_for_elements;
 | 
					static atomic_t tomoyo_policy_memory_size;
 | 
				
			||||||
/* Quota for holding non-string data. */
 | 
					/* Quota for holding policy. */
 | 
				
			||||||
static unsigned int tomoyo_quota_for_elements;
 | 
					static unsigned int tomoyo_quota_for_policy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * tomoyo_memory_ok - Check memory quota.
 | 
					 * tomoyo_memory_ok - Check memory quota.
 | 
				
			||||||
| 
						 | 
					@ -222,26 +222,30 @@ static unsigned int tomoyo_quota_for_elements;
 | 
				
			||||||
bool tomoyo_memory_ok(void *ptr)
 | 
					bool tomoyo_memory_ok(void *ptr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int allocated_len = ptr ? ksize(ptr) : 0;
 | 
						int allocated_len = ptr ? ksize(ptr) : 0;
 | 
				
			||||||
	bool result = false;
 | 
						atomic_add(allocated_len, &tomoyo_policy_memory_size);
 | 
				
			||||||
	if (!ptr || (tomoyo_quota_for_elements &&
 | 
						if (ptr && (!tomoyo_quota_for_policy ||
 | 
				
			||||||
		     tomoyo_allocated_memory_for_elements
 | 
							    atomic_read(&tomoyo_policy_memory_size)
 | 
				
			||||||
		     + allocated_len > tomoyo_quota_for_elements)) {
 | 
							    <= tomoyo_quota_for_policy)) {
 | 
				
			||||||
 | 
							memset(ptr, 0, allocated_len);
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	printk(KERN_WARNING "ERROR: Out of memory "
 | 
						printk(KERN_WARNING "ERROR: Out of memory "
 | 
				
			||||||
	       "for tomoyo_alloc_element().\n");
 | 
						       "for tomoyo_alloc_element().\n");
 | 
				
			||||||
	if (!tomoyo_policy_loaded)
 | 
						if (!tomoyo_policy_loaded)
 | 
				
			||||||
		panic("MAC Initialization failed.\n");
 | 
							panic("MAC Initialization failed.\n");
 | 
				
			||||||
	} else {
 | 
						return false;
 | 
				
			||||||
		result = true;
 | 
					 | 
				
			||||||
		tomoyo_allocated_memory_for_elements += allocated_len;
 | 
					 | 
				
			||||||
		memset(ptr, 0, allocated_len);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return result;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Memory allocated for string data in bytes. */
 | 
					/**
 | 
				
			||||||
static unsigned int tomoyo_allocated_memory_for_savename;
 | 
					 * tomoyo_memory_free - Free memory for elements.
 | 
				
			||||||
/* Quota for holding string data in bytes. */
 | 
					 *
 | 
				
			||||||
static unsigned int tomoyo_quota_for_savename;
 | 
					 * @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.
 | 
					 * 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
 | 
					 * "/lib/libc-2.5.so"), TOMOYO shares string data in the form of
 | 
				
			||||||
 * "const struct tomoyo_path_info *".
 | 
					 * "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.
 | 
					 * 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)
 | 
					const struct tomoyo_path_info *tomoyo_get_name(const char *name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	static DEFINE_MUTEX(lock);
 | 
					 | 
				
			||||||
	struct tomoyo_name_entry *ptr;
 | 
						struct tomoyo_name_entry *ptr;
 | 
				
			||||||
	unsigned int hash;
 | 
						unsigned int hash;
 | 
				
			||||||
	int len;
 | 
						int len;
 | 
				
			||||||
| 
						 | 
					@ -272,7 +277,7 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name)
 | 
				
			||||||
	len = strlen(name) + 1;
 | 
						len = strlen(name) + 1;
 | 
				
			||||||
	hash = full_name_hash((const unsigned char *) name, len - 1);
 | 
						hash = full_name_hash((const unsigned char *) name, len - 1);
 | 
				
			||||||
	head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)];
 | 
						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) {
 | 
						list_for_each_entry(ptr, head, list) {
 | 
				
			||||||
		if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name))
 | 
							if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name))
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
| 
						 | 
					@ -281,9 +286,9 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ptr = kzalloc(sizeof(*ptr) + len, GFP_KERNEL);
 | 
						ptr = kzalloc(sizeof(*ptr) + len, GFP_KERNEL);
 | 
				
			||||||
	allocated_len = ptr ? ksize(ptr) : 0;
 | 
						allocated_len = ptr ? ksize(ptr) : 0;
 | 
				
			||||||
	if (!ptr || (tomoyo_quota_for_savename &&
 | 
						if (!ptr || (tomoyo_quota_for_policy &&
 | 
				
			||||||
		     tomoyo_allocated_memory_for_savename + allocated_len
 | 
							     atomic_read(&tomoyo_policy_memory_size) + allocated_len
 | 
				
			||||||
		     > tomoyo_quota_for_savename)) {
 | 
							     > tomoyo_quota_for_policy)) {
 | 
				
			||||||
		kfree(ptr);
 | 
							kfree(ptr);
 | 
				
			||||||
		printk(KERN_WARNING "ERROR: Out of memory "
 | 
							printk(KERN_WARNING "ERROR: Out of memory "
 | 
				
			||||||
		       "for tomoyo_get_name().\n");
 | 
							       "for tomoyo_get_name().\n");
 | 
				
			||||||
| 
						 | 
					@ -292,14 +297,14 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name)
 | 
				
			||||||
		ptr = NULL;
 | 
							ptr = NULL;
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	tomoyo_allocated_memory_for_savename += allocated_len;
 | 
						atomic_add(allocated_len, &tomoyo_policy_memory_size);
 | 
				
			||||||
	ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
 | 
						ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
 | 
				
			||||||
	memmove((char *) ptr->entry.name, name, len);
 | 
						memmove((char *) ptr->entry.name, name, len);
 | 
				
			||||||
	atomic_set(&ptr->users, 1);
 | 
						atomic_set(&ptr->users, 1);
 | 
				
			||||||
	tomoyo_fill_path_info(&ptr->entry);
 | 
						tomoyo_fill_path_info(&ptr->entry);
 | 
				
			||||||
	list_add_tail(&ptr->list, head);
 | 
						list_add_tail(&ptr->list, head);
 | 
				
			||||||
 out:
 | 
					 out:
 | 
				
			||||||
	mutex_unlock(&lock);
 | 
						mutex_unlock(&tomoyo_name_list_lock);
 | 
				
			||||||
	return ptr ? &ptr->entry : NULL;
 | 
						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)
 | 
					int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!head->read_eof) {
 | 
						if (!head->read_eof) {
 | 
				
			||||||
		const unsigned int shared
 | 
							const unsigned int policy
 | 
				
			||||||
			= tomoyo_allocated_memory_for_savename;
 | 
								= atomic_read(&tomoyo_policy_memory_size);
 | 
				
			||||||
		const unsigned int private
 | 
					 | 
				
			||||||
			= tomoyo_allocated_memory_for_elements;
 | 
					 | 
				
			||||||
		char buffer[64];
 | 
							char buffer[64];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		memset(buffer, 0, sizeof(buffer));
 | 
							memset(buffer, 0, sizeof(buffer));
 | 
				
			||||||
		if (tomoyo_quota_for_savename)
 | 
							if (tomoyo_quota_for_policy)
 | 
				
			||||||
			snprintf(buffer, sizeof(buffer) - 1,
 | 
								snprintf(buffer, sizeof(buffer) - 1,
 | 
				
			||||||
				 "   (Quota: %10u)",
 | 
									 "   (Quota: %10u)",
 | 
				
			||||||
				 tomoyo_quota_for_savename);
 | 
									 tomoyo_quota_for_policy);
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			buffer[0] = '\0';
 | 
								buffer[0] = '\0';
 | 
				
			||||||
		tomoyo_io_printf(head, "Shared:  %10u%s\n", shared, buffer);
 | 
							tomoyo_io_printf(head, "Policy:  %10u%s\n", policy, buffer);
 | 
				
			||||||
		if (tomoyo_quota_for_elements)
 | 
							tomoyo_io_printf(head, "Total:   %10u\n", policy);
 | 
				
			||||||
			snprintf(buffer, sizeof(buffer) - 1,
 | 
					 | 
				
			||||||
				 "   (Quota: %10u)",
 | 
					 | 
				
			||||||
				 tomoyo_quota_for_elements);
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			buffer[0] = '\0';
 | 
					 | 
				
			||||||
		tomoyo_io_printf(head, "Private: %10u%s\n", private, buffer);
 | 
					 | 
				
			||||||
		tomoyo_io_printf(head, "Total:   %10u\n", shared + private);
 | 
					 | 
				
			||||||
		head->read_eof = true;
 | 
							head->read_eof = true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -373,9 +369,7 @@ int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head)
 | 
				
			||||||
	char *data = head->write_buf;
 | 
						char *data = head->write_buf;
 | 
				
			||||||
	unsigned int size;
 | 
						unsigned int size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sscanf(data, "Shared: %u", &size) == 1)
 | 
						if (sscanf(data, "Policy: %u", &size) == 1)
 | 
				
			||||||
		tomoyo_quota_for_savename = size;
 | 
							tomoyo_quota_for_policy = size;
 | 
				
			||||||
	else if (sscanf(data, "Private: %u", &size) == 1)
 | 
					 | 
				
			||||||
		tomoyo_quota_for_elements = size;
 | 
					 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue