4 * Implementation of the Domain-Based Mandatory Access Control.
6 * Copyright (C) 2005-2010 NTT DATA CORPORATION
11 #include <linux/kthread.h>
12 #include <linux/slab.h>
16 TOMOYO_ID_PATH_GROUP_MEMBER,
17 TOMOYO_ID_DOMAIN_INITIALIZER,
18 TOMOYO_ID_DOMAIN_KEEPER,
20 TOMOYO_ID_GLOBALLY_READABLE,
29 struct tomoyo_gc_entry {
30 struct list_head list;
34 static LIST_HEAD(tomoyo_gc_queue);
35 static DEFINE_MUTEX(tomoyo_gc_mutex);
37 /* Caller holds tomoyo_policy_lock mutex. */
38 static bool tomoyo_add_to_gc(const int type, void *element)
40 struct tomoyo_gc_entry *entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
44 entry->element = element;
45 list_add(&entry->list, &tomoyo_gc_queue);
49 static void tomoyo_del_allow_read
50 (struct tomoyo_globally_readable_file_entry *ptr)
52 tomoyo_put_name(ptr->filename);
55 static void tomoyo_del_file_pattern(struct tomoyo_pattern_entry *ptr)
57 tomoyo_put_name(ptr->pattern);
60 static void tomoyo_del_no_rewrite(struct tomoyo_no_rewrite_entry *ptr)
62 tomoyo_put_name(ptr->pattern);
65 static void tomoyo_del_domain_initializer
66 (struct tomoyo_domain_initializer_entry *ptr)
68 tomoyo_put_name(ptr->domainname);
69 tomoyo_put_name(ptr->program);
72 static void tomoyo_del_domain_keeper(struct tomoyo_domain_keeper_entry *ptr)
74 tomoyo_put_name(ptr->domainname);
75 tomoyo_put_name(ptr->program);
78 static void tomoyo_del_alias(struct tomoyo_alias_entry *ptr)
80 tomoyo_put_name(ptr->original_name);
81 tomoyo_put_name(ptr->aliased_name);
84 static void tomoyo_del_manager(struct tomoyo_policy_manager_entry *ptr)
86 tomoyo_put_name(ptr->manager);
89 static void tomoyo_del_acl(struct tomoyo_acl_info *acl)
92 case TOMOYO_TYPE_PATH_ACL:
94 struct tomoyo_path_acl *entry
95 = container_of(acl, typeof(*entry), head);
96 tomoyo_put_name_union(&entry->name);
99 case TOMOYO_TYPE_PATH2_ACL:
101 struct tomoyo_path2_acl *entry
102 = container_of(acl, typeof(*entry), head);
103 tomoyo_put_name_union(&entry->name1);
104 tomoyo_put_name_union(&entry->name2);
108 printk(KERN_WARNING "Unknown type\n");
113 static bool tomoyo_del_domain(struct tomoyo_domain_info *domain)
115 struct tomoyo_acl_info *acl;
116 struct tomoyo_acl_info *tmp;
118 * Since we don't protect whole execve() operation using SRCU,
119 * we need to recheck domain->users at this point.
121 * (1) Reader starts SRCU section upon execve().
122 * (2) Reader traverses tomoyo_domain_list and finds this domain.
123 * (3) Writer marks this domain as deleted.
124 * (4) Garbage collector removes this domain from tomoyo_domain_list
125 * because this domain is marked as deleted and used by nobody.
126 * (5) Reader saves reference to this domain into
127 * "struct linux_binprm"->cred->security .
128 * (6) Reader finishes SRCU section, although execve() operation has
130 * (7) Garbage collector waits for SRCU synchronization.
131 * (8) Garbage collector kfree() this domain because this domain is
133 * (9) Reader finishes execve() operation and restores this domain from
134 * "struct linux_binprm"->cred->security.
136 * By updating domain->users at (5), we can solve this race problem
137 * by rechecking domain->users at (8).
139 if (atomic_read(&domain->users))
141 list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) {
143 tomoyo_memory_free(acl);
145 tomoyo_put_name(domain->domainname);
150 static void tomoyo_del_name(const struct tomoyo_name_entry *ptr)
154 static void tomoyo_del_path_group_member(struct tomoyo_path_group_member
157 tomoyo_put_name(member->member_name);
160 static void tomoyo_del_path_group(struct tomoyo_path_group *group)
162 tomoyo_put_name(group->group_name);
165 static void tomoyo_collect_entry(void)
167 if (mutex_lock_interruptible(&tomoyo_policy_lock))
170 struct tomoyo_globally_readable_file_entry *ptr;
171 list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list,
173 if (!ptr->is_deleted)
175 if (tomoyo_add_to_gc(TOMOYO_ID_GLOBALLY_READABLE, ptr))
176 list_del_rcu(&ptr->list);
182 struct tomoyo_pattern_entry *ptr;
183 list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) {
184 if (!ptr->is_deleted)
186 if (tomoyo_add_to_gc(TOMOYO_ID_PATTERN, ptr))
187 list_del_rcu(&ptr->list);
193 struct tomoyo_no_rewrite_entry *ptr;
194 list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) {
195 if (!ptr->is_deleted)
197 if (tomoyo_add_to_gc(TOMOYO_ID_NO_REWRITE, ptr))
198 list_del_rcu(&ptr->list);
204 struct tomoyo_domain_initializer_entry *ptr;
205 list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list,
207 if (!ptr->is_deleted)
209 if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_INITIALIZER, ptr))
210 list_del_rcu(&ptr->list);
216 struct tomoyo_domain_keeper_entry *ptr;
217 list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
218 if (!ptr->is_deleted)
220 if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_KEEPER, ptr))
221 list_del_rcu(&ptr->list);
227 struct tomoyo_alias_entry *ptr;
228 list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
229 if (!ptr->is_deleted)
231 if (tomoyo_add_to_gc(TOMOYO_ID_ALIAS, ptr))
232 list_del_rcu(&ptr->list);
238 struct tomoyo_policy_manager_entry *ptr;
239 list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list,
241 if (!ptr->is_deleted)
243 if (tomoyo_add_to_gc(TOMOYO_ID_MANAGER, ptr))
244 list_del_rcu(&ptr->list);
250 struct tomoyo_domain_info *domain;
251 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
252 struct tomoyo_acl_info *acl;
253 list_for_each_entry_rcu(acl, &domain->acl_info_list,
256 case TOMOYO_TYPE_PATH_ACL:
257 if (container_of(acl,
258 struct tomoyo_path_acl,
261 struct tomoyo_path_acl,
265 case TOMOYO_TYPE_PATH2_ACL:
266 if (container_of(acl,
267 struct tomoyo_path2_acl,
274 if (tomoyo_add_to_gc(TOMOYO_ID_ACL, acl))
275 list_del_rcu(&acl->list);
279 if (!domain->is_deleted || atomic_read(&domain->users))
282 * Nobody is referring this domain. But somebody may
283 * refer this domain after successful execve().
284 * We recheck domain->users after SRCU synchronization.
286 if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, domain))
287 list_del_rcu(&domain->list);
294 for (i = 0; i < TOMOYO_MAX_HASH; i++) {
295 struct tomoyo_name_entry *ptr;
296 list_for_each_entry_rcu(ptr, &tomoyo_name_list[i],
298 if (atomic_read(&ptr->users))
300 if (tomoyo_add_to_gc(TOMOYO_ID_NAME, ptr))
301 list_del_rcu(&ptr->list);
310 struct tomoyo_path_group *group;
311 list_for_each_entry_rcu(group, &tomoyo_path_group_list, list) {
312 struct tomoyo_path_group_member *member;
313 list_for_each_entry_rcu(member, &group->member_list,
315 if (!member->is_deleted)
317 if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP_MEMBER,
319 list_del_rcu(&member->list);
323 if (!list_empty(&group->member_list) ||
324 atomic_read(&group->users))
326 if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP, group))
327 list_del_rcu(&group->list);
332 mutex_unlock(&tomoyo_policy_lock);
335 static void tomoyo_kfree_entry(void)
337 struct tomoyo_gc_entry *p;
338 struct tomoyo_gc_entry *tmp;
340 list_for_each_entry_safe(p, tmp, &tomoyo_gc_queue, list) {
342 case TOMOYO_ID_DOMAIN_INITIALIZER:
343 tomoyo_del_domain_initializer(p->element);
345 case TOMOYO_ID_DOMAIN_KEEPER:
346 tomoyo_del_domain_keeper(p->element);
348 case TOMOYO_ID_ALIAS:
349 tomoyo_del_alias(p->element);
351 case TOMOYO_ID_GLOBALLY_READABLE:
352 tomoyo_del_allow_read(p->element);
354 case TOMOYO_ID_PATTERN:
355 tomoyo_del_file_pattern(p->element);
357 case TOMOYO_ID_NO_REWRITE:
358 tomoyo_del_no_rewrite(p->element);
360 case TOMOYO_ID_MANAGER:
361 tomoyo_del_manager(p->element);
364 tomoyo_del_name(p->element);
367 tomoyo_del_acl(p->element);
369 case TOMOYO_ID_DOMAIN:
370 if (!tomoyo_del_domain(p->element))
373 case TOMOYO_ID_PATH_GROUP_MEMBER:
374 tomoyo_del_path_group_member(p->element);
376 case TOMOYO_ID_PATH_GROUP:
377 tomoyo_del_path_group(p->element);
380 printk(KERN_WARNING "Unknown type\n");
383 tomoyo_memory_free(p->element);
389 static int tomoyo_gc_thread(void *unused)
391 daemonize("GC for TOMOYO");
392 if (mutex_trylock(&tomoyo_gc_mutex)) {
394 for (i = 0; i < 10; i++) {
395 tomoyo_collect_entry();
396 if (list_empty(&tomoyo_gc_queue))
398 synchronize_srcu(&tomoyo_ss);
399 tomoyo_kfree_entry();
401 mutex_unlock(&tomoyo_gc_mutex);
406 void tomoyo_run_gc(void)
408 struct task_struct *task = kthread_create(tomoyo_gc_thread, NULL,
411 wake_up_process(task);